我正在尝试制作一个仿冒字符串结构,它将为我提供我需要的代码(我不需要所有内容,并希望尽可能快地使我的代码尽可能小)。因此,除了抓取strcpy
和strcmp
的来源(我允许这样做吗?)之外,我已经提出struct hstring
来帮助我的代码。到目前为止,我对struct
:
struct hstring{
private:
char *s; // pointer to what holds the string
int size; // size of the string
public:
hstring(){
s=(char *)malloc(0);
size=0;
}
void set(const char* str){ // set the string
size=0;
while(str[size]!='\0')
size++;
s=(char*)realloc((void *)s,size*sizeof(*s)); // reallocate memory to hold just enough for the character array
for(int i=0;i<size;i++)
s[i]=str[i];
s[size]='\0';
}
bool is(const char* str){ // check if something is equal to the string
int i=0;
while((s[i]==str[i])&&(str[i]!='\0'))
i++;
if((i==size)&&(str[i]=='\0'))
return true;
return false;
}
inline char* get(){ // return the string
return s;
}
inline int length(){ // return the size of the string
return size;
}
};
我注意到set()
函数工作的唯一方法是在那里放一个显式字符串或者没有数组。对于前。
// This works
printf("\nTest1\n");
hstring test;
char tmp_c[50];
scanf("%s",tmp_c);
test.set(tmp_c);
printf("%s\n",test.get());
// This works
printf("\nTest2\n");
hstring test2[2];
test2[0].set("Hello ");
test2[1].set("world!");
printf("%s %s\n",test2[0].get(),test2[1].get());
// This works
printf("\nTest3\n");
hstring test3[2];
scanf("%s",tmp_c);
test3[0].set(tmp_c);
scanf("%s",tmp_c);
test3[1].set(tmp_c);
printf("%s %s\n",test3[0].get(),test3[1].get());
// This, what I want to do, does NOT work
printf("\nTest4\n");
hstring *test4 = (hstring *)malloc(2*sizeof(hstring));
for(int i=0;i<2;i++){
scanf("%s",tmp_c);
test4[i].set(tmp_c);
}
printf("%s %s",test4[0],test4[1]);
free(test4);
我很困惑为什么第四次测试没能正常运行。它会在到达test4并尝试在.set()
函数中重新分配内存时进行编译但崩溃。我得到一个“访问违规读取位置”错误,这让我觉得我正在写/读某个我不应该的地方;但是,我无法确定确切的原因(虽然我可以告诉导致错误的行是s=(char*)realloc((void *)s,size*sizeof(*s));
,但是在尝试重新分配字符数组的大小时。有人注意到我忽略了一个问题吗?
答案 0 :(得分:2)
对于test4
,您使用malloc()
为两个对象分配内存:
hstring *test4 = (hstring *)malloc(2*sizeof(hstring));
但是,不会为其中任何一个调用构造函数。因此,test4[0]
和test4[1]
都未正确初始化。您的类方法可能假设引用的对象是已初始化,因此您会得到非确定性行为。
解决此问题的方法是不使用malloc()
分配test4
,而是使用std::vector
代替:
std::vector<hstring> test4(2);
然后,您可以移除对free()
的来电,因为当对象超出范围时,test4
将被正确销毁。
hstring
类本身正在管理指向已分配内存的指针。因此,您需要为它定义一个析构函数来释放该内存。
struct hstring {
//...
~hstring () { free(s); }
//...
};
但是,因为析构函数已经变得必要,所以现在还需要为hstring
类定义复制构造函数和赋值运算符。这称为Rule of Three。
您可以通过利用对象为您管理内存来避免这种复杂性。对于您的hstring
课程,最简单的方法是将内部char *
改为std::vector<char>
。然后就不需要析构函数,复制构造函数和赋值运算符。
答案 1 :(得分:1)
将0传递给malloc
或者返回NULL或可用于调用free的特殊指针,最好只使用NULL
初始化或者更好地使用'\ 0'进行初始化字符。
您正在打印正在打印结构的printf("%s %s",test4[0],test4[1]);
。要打印字符串,您应该printf("%s %s",test4[0].get (),test4[1].get ());
此外,程序中存在内存泄漏。您在malloc
结构对象中realloc
编辑并s
编了hstring
指针,但从未释放过它们。
我注意到当你做malloc时没有调用构造函数。您需要使用new
/ delete
代替malloc
/ free
您需要做的最小更改:分配时hstring *test4 = new hstring[2];
和释放时delete [] test4
。
请参阅jxh的建议。