【问题标题】:Why this code giving run time exception when free-ing the pointer为什么此代码在释放指针时会给出运行时异常
【发布时间】:2012-12-22 07:01:29
【问题描述】:

我有简单的代码,

#include "stdafx.h"
#include <malloc.h>
int main()
{
  char *p = (char*) malloc(10);
  p = "Hello";

  free(p);

  return 0;
}

此代码在终止时给出运行时异常。以下是最简单的错误,


Microsoft Visual C++ 调试库

调试断言失败!

程序:...\我的文档\visual studio 2010\Projects\samC\Debug\samC.exe 文件:f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c 线路:1322

表达式:_CrtIsValidHeapPointer(pUserData)

有关您的程序如何导致断言的信息 失败,请参阅有关断言的 Visual C++ 文档。

(按重试调试应用程序)

中止重试忽略

【问题讨论】:

  • std::string 用于您期望的字符串语义。
  • 您将 p = "Hello" 与 strcpy(p, "hello) 混淆了
  • 这是一个C代码,所以我需要使用char *,其次我没有得到异常的原因。
  • @PranitPKothari,如果是 C,为什么用 C++ 标记?
  • @chris,抱歉,已编辑标签。

标签: c runtime


【解决方案1】:

p = "Hello"; 使p 指向字符串文字并丢弃先前分配的值。您不能 free 字符串文字。你不能修改它。

如果您希望p 保存该字符串,只需使用

char* p = "Hello";

char p[] = "Hello";

如果你打算修改它。

两者都不需要free

【讨论】:

  • 那么使用malloc分配的内存会发生什么?
  • @PranitPKothari 会泄露的。
【解决方案2】:

这就是你如何在 malloc 分配的内存中写入一个字符串到一个 char 指针。

strcpy(p, "Hello");

换行

p = "Hello";

使用 strcpy 一个 & 你的程序会正常工作。

你还需要

#include <string.h>

malloc 返回一个指向已分配内存的指针。假设地址是 95000(只是我抽出来的一个随机数)。

所以在 malloc -p 之后会保存地址95000 包含95000 的p 是内存地址,当你用完内存时需要传递给free。

但是,下一行 p = "Hello"; 将字符串文字“Hello”的地址(即存在于地址 25000)放入 p。

因此,当您执行 free(p) 时,您正在尝试释放不是由 malloc 分配的 25000

OTOH,当您strcpy 时,您将字符串“Hello”复制到从 p 开始的地址中(即95000)。 p 在 strcpy 之后仍然是 95000

free(p) 释放了正确的内存。

您也可以避免使用malloc 并使用

char *p = "Hello";

但是,在这种方法中,您不能修改字符串。

即如果在此之后您执行*p = 'B' 将字符串更改为Bello,它将成为未定义的操作。 malloc 的方式不是这样。

如果你使用

char p[] = "Hello";

char p[10] = "Hello";

你会得到一个可修改的字符串,它不必是freed。

【讨论】:

    【解决方案3】:
    p = "Hello";
    free(p);
    

    由于Hello 是静态分配的,你不能free 它。我不确定你为什么分配一些内存只是为了通过将指针更改为另一个指针来丢弃指针,但这没有任何效果。如果你这样做:

    int i = 1;
    i = 2;
    

    i 不记得它曾经拥有一个1,它现在拥有一个2。同样,p 没有内存,它曾经持有指向您分配的某些内存的指针。它现在拥有一个指向不可变常量的指针。

    【讨论】:

      【解决方案4】:

      这是一个不错的选择。 字符序列“hello”是常量,因此既不在堆上也不在堆栈上,而是在 .bss/.data 段中。当您执行p="hello" 时,您使p 指向该段中字符串hello 的地址,而不是您使用malloc 在堆上分配的内存。当您转到free p 时,它会尝试释放 .bss/.data 段中的内存,自然会失败。

      您可能想要的是strcpy(p,"hello"); 之类的东西,它遍历“hello”中的每个字符并将其放置在 p 指向的内存中。本质上是在内存地址 p 处创建字符串“hello”的副本。

      【讨论】:

        【解决方案5】:

        如果要将字符串“Hello”的内容复制到你分配的内存中,需要使用strcpy

        strcpy(p, "Hello");
        

        线

        p = "Hello";
        

        将字符串文字“Hello”的地址分配给指针p,覆盖从malloc返回的指针值,因此调用free时会崩溃。

        【讨论】:

          猜你喜欢
          • 2023-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多