-4

我正在尝试制作一个仿冒字符串结构,它将为我提供我的代码所需的基本内容(我不需要所有东西,并且想让我的代码尽可能快和小)。因此,除了获取源代码strcpystrcmp(我可以这样做吗?)之外,我还做了一个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));在尝试重新分配字符数组的大小时。有人注意到我忽略的问题吗?

4

2 回答 2

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类定义一个复制构造函数和一个赋值运算符。这被称为三法则

您可以通过使用对象为您管理内存来避免这种复杂性。对于您的hstring班级,改为使用内部char *a可能是最简单的std::vector<char>。这样就不需要析构函数、复制构造函数和赋值运算符了。

于 2013-07-24T04:56:58.690 回答
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 的建议。

于 2013-07-24T04:49:42.773 回答