无法使用字符串作为类属性(请参阅更新 4)
以此类为例:
#include <string>
using namespace std;
class One {
private:
string * text;
public:
One();
~One();
void setText(string value);
string uppercase();
string lowercase();
string inverted();
};
其实现:
#include "libone.h"
One::One() {
text = new string();
}
One::~One() {
delete text;
}
void One::setText(string value) {
//
}
string One::uppercase() {
string result(*this->text);
for(int i=0; i<result.size(); i++) {
char c = result[i];
c = toupper(c);
result[i] = c;
}
return result;
}
string One::lowercase() {
string result(*this->text);
for(int i=0; i<result.size(); i++) {
char c = result[i];
c = tolower(c);
result[i] = c;
}
return result;
}
string One::inverted() {
string result;
string temp(*this->text);
for(int i=temp.size(); i>0; i--) {
result = result + temp.at(i);
}
return result;
}
此处使用:
#include <libone.h>
int main(int argc, char *argv[]) {
One one;
one.setText("Kleber Mota de Oliveira");
cout << "text:" << one.uppercase() << endl;
cout << "text:" << one.lowercase() << endl;
return 1;
}
programa 编译时没有错误或警告,但是当我尝试运行可执行文件时,出现分段错误。
我也尝试使用 string text
作为属性,但发生了同样的问题。
我的另一个项目也发生了类似的情况。任何人都可以告诉我我在这里做错了什么?
libone.cpp 的 Makefile
all: libone
libone: ${obj_dir}/libone.o
g++ -shared -o ${release_dir}/libone.so ${obj_dir}/libone.o -Wl,--out-implib,${release_dir}/libone.a
${obj_dir}/libone.o: src/libone.cpp
g++ -fPIC -c src/libone.cpp -o ${obj_dir}/libone.o
Main.cpp 的 Makefile
all: main
main: ${obj_dir}/Main.o
g++ -L ${release_dir} -o ${release_dir}/project -Wl,-rpath='./' ${obj_dir}/Main.o -lone -ltwo
${obj_dir}/Main.o: Main.cpp
g++ -I ${lib_one_header} -I ${lib_two_header} -c Main.cpp -o ${obj_dir}/Main.o
Makefile
export base_dir := ${CURDIR}
export obj_dir := ${base_dir}/build
export release_dir := ${base_dir}/release
export main_src := ${base_dir}/src
export lib_one_header := ${base_dir}/src/libone/include
export lib_one_src := ${base_dir}/src/libone
export lib_two_header := ${base_dir}/src/libtwo/include
export lib_two_src := ${base_dir}/src/libtwo
lib_one := ${lib_one_src}
lib_two := ${lib_two_src}
libraries := $(lib_one) $(lib_two)
player := ${main_src}
.PHONY: all $(player) $(libraries)
all: $(player)
$(player) $(libraries): | ${obj_dir} ${release_dir}
$(MAKE) --directory=$@
$(player): $(libraries)
更新 1
如果我尝试构建 libone. cpp
和 Main.cpp
一起:
g++ libone.cpp Main.cpp -o main
仅生成一个可执行文件,一切正常。但是,如果我使用 Makefile 进行构建,以获得单独的库和可执行文件,那么我会收到此分段错误错误。
UPDATE 2
gdb shell 中 backtrace 命令的
#0 0x00007ffff7bd84ec in __memmove_avx_unaligned_erms () from /usr/lib/libc.so.6
#1 0x00007ffff7ea6296 in std::char_traits<char>::copy (__n=23, __s2=<optimized out>, __s1=<optimized out>)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/char_traits.h:409
#2 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy (__n=23, __s=<optimized out>, __d=<optimized out>)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:359
#3 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy (__n=23, __s=<optimized out>, __d=<optimized out>)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:354
#4 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign (this=this@entry=0x7fffffffd9ce, __str="Kleber Mota de Oliveira")
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.tcc:272
#5 0x00007ffff7ea662f in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::assign (__str=..., this=0x7fffffffd9ce)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:1355
#6 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator= (this=0x7fffffffd9ce, __str=...)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:680
#7 0x00007ffff7fba255 in One::setText(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) () from ./libone.so
#8 0x000055555555637d in main ()
结果(使用 string text
作为属性:(使用 string * text
作为属性):
#0 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign (this=this@entry=0x55555556bee0beb0, __str="Kleber Mota de Oliveira")
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.tcc:260
#1 0x00007ffff7ea662f in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::assign (__str=..., this=0x55555556bee0beb0)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:1355
#2 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator= (this=0x55555556bee0beb0, __str=...)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:680
#3 0x00007ffff7fba2a6 in One::setText(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) () from ./libone.so
#4 0x000055555555637d in main ()
UPDATE 3
通过此更新,仅执行 Main.cpp
中的第一个方法,在第二个方法中,我收到了分段错误错误:
class One {
private:
char * text;
public:
One();
~One();
void setText(char* value);
string uppercase();
string lowercase();
string inverted();
};
实现:
void One::setText(char* value) {
text = value;
}
string One::uppercase() {
string result = text;
for(int i=0; i<result.size(); i++) {
char c = result[i];
c = toupper(c);
result[i] = c;
}
return result;
}
string One::lowercase() {
string result(text);
for(int i=0; i<result.size(); i++) {
char c = result[i];
c = tolower(c);
result[i] = c;
}
return result;
}
string One::inverted() {
string result;
string temp(text);
for(int i=temp.size()-1; i>=0; i--) {
result = result + temp[i];
}
return result;
}
UPDATE 4
。代码下面,Main.cpp
中调用的所有方法都被执行,但在屏幕上显示一堆垃圾。 示例:
text:�Q���
text:�Q���
text:���t
类声明:
class One {
private:
char * text;
public:
One();
~One();
void setText(char* value);
const char * uppercase();
const char * lowercase();
const char * inverted();
};
实现:
const char * One::uppercase() {
string result = text;
for(int i=0; i<result.size(); i++) {
char c = result[i];
c = toupper(c);
result[i] = c;
}
return result.c_str();
}
const char * One::lowercase() {
string result(text);
for(int i=0; i<result.size(); i++) {
char c = result[i];
c = tolower(c);
result[i] = c;
}
return result.c_str();
}
const char * One::inverted() {
string result;
string temp(text);
for(int i=temp.size()-1; i>=0; i--) {
result = result + temp[i];
}
return result.c_str();
}
UPDATE 5
类声明:
class One {
private:
char * text;
public:
One();
~One();
void setText(const char * value);
const char * uppercase();
const char * lowercase();
const char * inverted();
};
实现。 :
#include "libone.h"
#include <iostream>
using namespace std;
One::One() {
text = new char[1];
text[0] = '\0';
}
One::~One() {
delete [] text;
}
void One::setText(const char * value) {
delete [] text;
int size = 0;
for(; value[size] != '\0'; size++);
text = new char[size];
for(int i=0; i<size; i++)
text[i] = value[i];
}
const char * One::uppercase() {
char * result;
int size = 0;
for(; text[size] != '\0'; size++);
result = new char[size];
for(int i=0; i<size; i++) {
if (text[i] >= 65 && text[i] <= 90)
result[i] = text[i] - 32;
else
result[i] = text[i];
}
return result;
}
const char * One::lowercase() {
char * result;
int size = 0;
for(; text[size] != '\0'; size++);
result = new char[size];
for(int i=0; i<size; i++) {
if (text[i] >= 33 && text[i] <= 58)
result[i] = text[i] + 32;
else
result[i] = text[i];
}
return result;
}
const char * One::inverted() {
char * result;
int size = 0;
for(; text[size] != '\0'; size++)
result = new char[size];
for(int i=0; i<size; i++) {
result[i] = text[size-(i+1)];
}
result[size] = '\0';
return result;
}
Main.cpp
#include "libone.h"
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
One one;
one.setText(argv[1]);
cout << one.uppercase() << endl;
cout << one.lowercase() << endl;
cout << one.inverted() << endl;
return 1;
}
输出:
+leber -ota de /liveira
Kleber Mota de Oliveira
arievilO ed atoM rebelK
*** stack smashing detected ***: terminated
zsh: IOT instruction (core dumped)
Take this class as example:
#include <string>
using namespace std;
class One {
private:
string * text;
public:
One();
~One();
void setText(string value);
string uppercase();
string lowercase();
string inverted();
};
its implementation:
#include "libone.h"
One::One() {
text = new string();
}
One::~One() {
delete text;
}
void One::setText(string value) {
//
}
string One::uppercase() {
string result(*this->text);
for(int i=0; i<result.size(); i++) {
char c = result[i];
c = toupper(c);
result[i] = c;
}
return result;
}
string One::lowercase() {
string result(*this->text);
for(int i=0; i<result.size(); i++) {
char c = result[i];
c = tolower(c);
result[i] = c;
}
return result;
}
string One::inverted() {
string result;
string temp(*this->text);
for(int i=temp.size(); i>0; i--) {
result = result + temp.at(i);
}
return result;
}
used here:
#include <libone.h>
int main(int argc, char *argv[]) {
One one;
one.setText("Kleber Mota de Oliveira");
cout << "text:" << one.uppercase() << endl;
cout << "text:" << one.lowercase() << endl;
return 1;
}
programa compile without errors or warnings, but when I try to run the executable, I got an segmentation fault.
I tried use string text
as atribute too, but the same problem happens.
Something similar is happening with another project mine. Anyone can tell me what I am doing wrong here?
Makefile for libone.cpp
all: libone
libone: ${obj_dir}/libone.o
g++ -shared -o ${release_dir}/libone.so ${obj_dir}/libone.o -Wl,--out-implib,${release_dir}/libone.a
${obj_dir}/libone.o: src/libone.cpp
g++ -fPIC -c src/libone.cpp -o ${obj_dir}/libone.o
Makefile for Main.cpp
all: main
main: ${obj_dir}/Main.o
g++ -L ${release_dir} -o ${release_dir}/project -Wl,-rpath='./' ${obj_dir}/Main.o -lone -ltwo
${obj_dir}/Main.o: Main.cpp
g++ -I ${lib_one_header} -I ${lib_two_header} -c Main.cpp -o ${obj_dir}/Main.o
Makefile
export base_dir := ${CURDIR}
export obj_dir := ${base_dir}/build
export release_dir := ${base_dir}/release
export main_src := ${base_dir}/src
export lib_one_header := ${base_dir}/src/libone/include
export lib_one_src := ${base_dir}/src/libone
export lib_two_header := ${base_dir}/src/libtwo/include
export lib_two_src := ${base_dir}/src/libtwo
lib_one := ${lib_one_src}
lib_two := ${lib_two_src}
libraries := $(lib_one) $(lib_two)
player := ${main_src}
.PHONY: all $(player) $(libraries)
all: $(player)
$(player) $(libraries): | ${obj_dir} ${release_dir}
$(MAKE) --directory=$@
$(player): $(libraries)
UPDATE 1
If I try build libone.cpp
and Main.cpp
together with:
g++ libone.cpp Main.cpp -o main
generating only one executable, everything works fine. But if I build with the Makefiles, to get separate library and executable, then I got this Segmentation fault error.
UPDATE 2
result of the backtrace command in gdb shell (using string text
as atribute:
#0 0x00007ffff7bd84ec in __memmove_avx_unaligned_erms () from /usr/lib/libc.so.6
#1 0x00007ffff7ea6296 in std::char_traits<char>::copy (__n=23, __s2=<optimized out>, __s1=<optimized out>)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/char_traits.h:409
#2 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy (__n=23, __s=<optimized out>, __d=<optimized out>)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:359
#3 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy (__n=23, __s=<optimized out>, __d=<optimized out>)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:354
#4 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign (this=this@entry=0x7fffffffd9ce, __str="Kleber Mota de Oliveira")
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.tcc:272
#5 0x00007ffff7ea662f in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::assign (__str=..., this=0x7fffffffd9ce)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:1355
#6 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator= (this=0x7fffffffd9ce, __str=...)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:680
#7 0x00007ffff7fba255 in One::setText(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) () from ./libone.so
#8 0x000055555555637d in main ()
(using string * text
as atribute):
#0 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign (this=this@entry=0x55555556bee0beb0, __str="Kleber Mota de Oliveira")
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.tcc:260
#1 0x00007ffff7ea662f in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::assign (__str=..., this=0x55555556bee0beb0)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:1355
#2 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator= (this=0x55555556bee0beb0, __str=...)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:680
#3 0x00007ffff7fba2a6 in One::setText(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) () from ./libone.so
#4 0x000055555555637d in main ()
UPDATE 3
With this update, only the first method in Main.cpp
is executed. In the second I got a Segmentation fault error:
class One {
private:
char * text;
public:
One();
~One();
void setText(char* value);
string uppercase();
string lowercase();
string inverted();
};
implementation:
void One::setText(char* value) {
text = value;
}
string One::uppercase() {
string result = text;
for(int i=0; i<result.size(); i++) {
char c = result[i];
c = toupper(c);
result[i] = c;
}
return result;
}
string One::lowercase() {
string result(text);
for(int i=0; i<result.size(); i++) {
char c = result[i];
c = tolower(c);
result[i] = c;
}
return result;
}
string One::inverted() {
string result;
string temp(text);
for(int i=temp.size()-1; i>=0; i--) {
result = result + temp[i];
}
return result;
}
UPDATE 4
with the code below, all methods called in Main.cpp
are executed, but display a bunch of rubish in the screen. An example:
text:�Q���
text:�Q���
text:���t
class declaration:
class One {
private:
char * text;
public:
One();
~One();
void setText(char* value);
const char * uppercase();
const char * lowercase();
const char * inverted();
};
implementation:
const char * One::uppercase() {
string result = text;
for(int i=0; i<result.size(); i++) {
char c = result[i];
c = toupper(c);
result[i] = c;
}
return result.c_str();
}
const char * One::lowercase() {
string result(text);
for(int i=0; i<result.size(); i++) {
char c = result[i];
c = tolower(c);
result[i] = c;
}
return result.c_str();
}
const char * One::inverted() {
string result;
string temp(text);
for(int i=temp.size()-1; i>=0; i--) {
result = result + temp[i];
}
return result.c_str();
}
UPDATE 5
class declaration:
class One {
private:
char * text;
public:
One();
~One();
void setText(const char * value);
const char * uppercase();
const char * lowercase();
const char * inverted();
};
implementation:
#include "libone.h"
#include <iostream>
using namespace std;
One::One() {
text = new char[1];
text[0] = '\0';
}
One::~One() {
delete [] text;
}
void One::setText(const char * value) {
delete [] text;
int size = 0;
for(; value[size] != '\0'; size++);
text = new char[size];
for(int i=0; i<size; i++)
text[i] = value[i];
}
const char * One::uppercase() {
char * result;
int size = 0;
for(; text[size] != '\0'; size++);
result = new char[size];
for(int i=0; i<size; i++) {
if (text[i] >= 65 && text[i] <= 90)
result[i] = text[i] - 32;
else
result[i] = text[i];
}
return result;
}
const char * One::lowercase() {
char * result;
int size = 0;
for(; text[size] != '\0'; size++);
result = new char[size];
for(int i=0; i<size; i++) {
if (text[i] >= 33 && text[i] <= 58)
result[i] = text[i] + 32;
else
result[i] = text[i];
}
return result;
}
const char * One::inverted() {
char * result;
int size = 0;
for(; text[size] != '\0'; size++)
result = new char[size];
for(int i=0; i<size; i++) {
result[i] = text[size-(i+1)];
}
result[size] = '\0';
return result;
}
Main.cpp
#include "libone.h"
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
One one;
one.setText(argv[1]);
cout << one.uppercase() << endl;
cout << one.lowercase() << endl;
cout << one.inverted() << endl;
return 1;
}
output:
+leber -ota de /liveira
Kleber Mota de Oliveira
arievilO ed atoM rebelK
*** stack smashing detected ***: terminated
zsh: IOT instruction (core dumped)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
没有充分的理由使
text
成员成为string*
指针(特别是因为您没有遵循 3/5/0 规则来正确管理指针,但在本练习中我们可以忽略它,因为您没有复制一个
目的)。但是,为了便于讨论,我们只是说,无论出于何种原因,您都需要一个指针。您的代码犯的唯一错误是:
setText()
中,您没有将value
分配给text
,例如:inverse 中()
,您正在越界访问temp
字符串,它应该是这样的:您显示的其余代码工作正常:
在线演示
更新:
您的代码问题在于您正在动态库中实现
One
。因此,您无法跨库边界传递非 POD 类型,例如std::string
。因此,尝试更像这样的事情:或者:
There is no good reason to make the
text
member be astring*
pointer (especially since you are not following the Rule of 3/5/0 to manage the pointer properly, but we can ignore that for this exercise since you are not making any copies of theone
object).But, let's just say, for the sake of argument, that you need a pointer, for whatever reason. The only mistakes your code is making are:
setText()
, you are not assigningvalue
totext
, eg:inverse()
, you are accessing thetemp
string out of bounds, it should be like this instead:The rest of the code you have shown works fine:
Online Demo
UPDATE:
The problem with your code is that you are implementing
One
in a dynamic library. As such, you can't pass non-POD types, likestd::string
, across the library boundary. So, try something more like this instead:Alternatively: