首页 > 解决方案 > 如何使用 char* 修复此内存泄漏?

问题描述

我正在写一个简短的方法来获取达尔文的 MAC 地址。但是,我不断收到以下错误消息:

malloc: can't allocate region
*** mach_vm_map(size=3907498536060022784) failed (error code=3)
malloc: *** set a breakpoint in malloc_error_break to debug

我认为这是由于内存泄漏。

我尝试通过char* addr引用传递变量,但没有成功。

我的方法是:

char* getPhysicalAddress() {

    char* addr;
    #ifdef __APPLE__

        FILE *fp = popen("ifconfig en0 | awk '/ether/{print $2}'", "r");

        if (fp != NULL) {
            fscanf(fp, "%s", addr);

            pclose(fp);
        }
        else {
            addr = "[unknown]";
        }

    #endif

    #ifdef __linux__

        FILE* file = popen("cat /sys/class/net/eth0/address", "r");

        if (file != NULL) {
            fscanf(file, "%s", addr);

            pclose(file);
        }
        else {
            addr = "[unknown]";
        }

    #endif

    return addr;
}

在我的主函数中,我用char* addr = getPhysicalAddress();.

如何修复此方法中的内存泄漏?

标签: c++memory-leaks

解决方案


让我们看一下这段代码:

char* addr;
...
fscanf(fp, "%s", addr);

看起来,从这段代码中,您想从fp文件中读取字符串addr。但是,正如所写的那样,此代码会导致未定义的行为(哦,不!),并且在您的情况下,它看起来会破坏您的内存管理器,因此会malloc出现错误。

那么这里发生了什么?请记住,这addr并不是真正的字符串。相反,它是 a char*,这意味着它是一个变量,表示“请查看我所指的位置,您会找到存储一些字符的空间”。但是,您未对其进行初始化,这意味着它指向内存中的某个随机区域,可能是您实际上并不拥有的空间。当然fscanf后尝试将它读取的字符写入该位置时,它会破坏碰巧在该位置的任何内存,这是一件坏事。

换句话说,这不是内存泄漏。相反,它是一个未初始化的指针写入。

有几个选项可以解决这个问题。一种选择是将addra转换char*为实际的字符数组,这意味着它addr本身将表示“这里有一些空间可以放置一些字符”。您需要调整fscanf调用以确保您没有读取太多字符,否则您将面临溢出缓冲区的风险。

或者,由于您已经用 C++ 标记了它,另一种选择是使用类似的类型std::string来保存内存,然后使用循环从 中提取字符fp,将它们附加到该std::string对象。

希望这可以帮助!


推荐阅读