【问题标题】:class destructor changes the program result类析构函数改变程序结果
【发布时间】:2019-12-26 13:42:38
【问题描述】:

如果我评论析构函数并打印“Hello world”,下面的代码可以正常工作 如果没有评论它只打印“你好”! 注意我在 windows xp 32bits 上使用 mingw 4.9 而且机器很旧 pintume 4 1.8ghz

奇怪的是这段代码在其他现代电脑上运行正常,我只在这台旧电脑上得到这个错误

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct String{
public:
    String(const char * txt){
        len = strlen(txt);
        if (len > 0)
            buffer = (char*) malloc(len);
        strcpy(buffer,txt);
    }
    void add(const char * txt){
        realloc(buffer,len+strlen(txt));
        strcpy(buffer+len,txt);
        len += strlen(txt);
    }
    ~String(){ if (len > 0) free(buffer);} // if commented it works fine !!!
    char* get_ptr(){ return buffer;}
private:
    char * buffer;
    int len;    
};

int main(){
    String s("Hello");
    s.add(" World");
    printf(s.get_ptr());
    getchar();
}

【问题讨论】:

  • realloc 不能以这种方式工作,您必须使用它的结果。此外,在 C++ 中使用 C 分配函数很奇怪。您还应该处理 len=0 的情况。
  • 你是对的,但是我在两种方式上都得到了相同的结果,关于 c 分配函数,我认为如果只与基元类型一起使用就可以了
  • 除了没有正确使用realloc(),你没有分配正确的长度。要保存具有 strlen()strcpy() 等函数的 C 样式字符串,必须为终止的 nul(值为 '\0' 的字节)包含空间,否则行为未定义。因此,您需要将传递给malloc()realloc() 的长度(由strlen() 返回)加一。更好的是,使用标准库类型 std::string 而不是滚动您自己的字符串类型。

标签: c++


【解决方案1】:

std::realoc 有一个返回值,它返回指向重新分配的内存区域的指针。如果缓冲区后面有足够的可用空间,此地址可以与输入地址相同,也可以是新地址。

因此,如果 realloc(buffer,len+strlen(txt)); 返回的指针与存储在 buffer 中的指针不同,那么您将继续使用无效指针,从而导致未定义的行为。所以对于它工作的 PC,可能是因为 realloc 返回相同的指针,或者只是因为未定义的行为确实导致了“正确”的结果。

更改代码(从析构函数中添加/删除代码)将导致不同的内存布局,这也可能导致未定义行为的不同结果。

不管怎样,realloc 是在 C++ 中解决该问题的错误方法。您应该在此处使用std::string(或者如果不想要字符串,但可以使用可以调整大小的缓冲区,也可以使用std::vector&lt;char&gt;)。

【讨论】:

  • 谢谢你的信息,我把这个程序翻译成free pascal,看起来效果很好,我用的是free pascal rtl提供的ReallocMem,我不知道它的内部代码,但应该是一样的作为 c realloc !!
  • 好像 buffer = realloc(buffer,len+strlen(txt)) 解决了问题,谢谢
猜你喜欢
  • 2012-01-19
  • 2011-09-28
  • 2021-12-24
  • 2014-12-06
  • 2020-11-09
  • 1970-01-01
  • 2012-06-26
  • 2022-11-05
  • 2020-10-03
相关资源
最近更新 更多