首页 文章

C动态结构(malloc和free)

提问于
浏览
2

我正在尝试学习C,C编程的基础知识,所以我从“C”开始 . 我有很多使用Java和VB编程的经验 . 但“C”是我想学的东西 . 所以我遇到了一个问题,试图理解“malloc”和“free”函数 .

我在Windows 98上使用Borland C 4.5和Visual C 6.0 . - (只是一个测试环境,想学习非常基础和早期的Windows编程) .

请参阅此代码:

struct String
{
 char *value;
 int length;
};
char *initString(const char *value)
{
 char *str = (char*)malloc( strlen(value)+1 );
 strcpy(str, value);
 return str;
}

struct String *InitString(const char *text)
{
 struct String *str = (struct String*)malloc( sizeof(struct String) );

 str->value = initString(text);
 str->length = strlen( str->value );
 return str;
}
void freeString(struct String *str)
{
 free(str->value);
 free(str);
 str = NULL;
}
int main(int argv, char *argc[])
{
 struct String *theString = InitString("Testring string struct");

 printf("String: %s\n", theString->value);
 printf("String Length: %d\n", theString->length);

 freeString(theString);

 printf("\nData: %s", theString->value);

 return 0;
}

该程序运行时,结果是正确的 .
在我调用“ freeString(theString) ", the function does free the memory and set the struct to NULL inside the " freeString()" function, that should free the " theString " inside " main()" as I pass in the pointer to " theString ", but when the function returns: " theString " is not " NULL”之后 .

在Borland 4.5上,我仍然可以使用“theString-> value”调用“printf”并打印字符串 . 在Visual C上,程序在调用“printf”时崩溃 - 但“theString”仍然不是“NULL” . 当我在调试模式下跟踪程序时,“struct”在“freeString()”函数内被释放,并且struct被设置为NULL,但是当函数返回时,“theString”不是NULL并且“value”是仍可用于Borland,但不适用于Visual C.

所以我想了解,这里发生了什么?是否应该进行一些去引用?

先感谢您!

5 回答

  • 1

    你正在看undefined behavior(你're using a value after it has been free'),所以真的 - 任何事情都可能发生 . 它可能会崩溃,或者它可以运行"normally"

    可能发生的事情是msvc,至少在调试模式下,将特殊字节模式归零或写入你释放的内存,这样str->值指针变为无效并在你取消引用它时崩溃,而borland只是将内存释放回内存游泳池,但没有动摇 .

    你的 str=NULL 在函数中

    void freeString(struct String *str)
    {
     free(str->value);
     free(str);
     str = NULL;
    }
    

    没有实际效果 . 它只是将本地 str 值设置为NULL,调用者不受影响 .

    如果要将调用者的指针设置为NULL,则必须传入指向该指针的指针,或者在C的情况下,传递对指针的引用 .

    void freeString(struct String *&str) //c++
    {
     free(str->value);
     free(str);
     str = NULL;
    }
    
    
    void freeString(struct String **str) //c, call it as freeString(&theString);
    {
     free((*str)->value);
     free(*str);
     *str = NULL;
    }
    
  • 3

    这是你永远不应该在它指向的内存被释放后使用指针的原因之一 . 行为是未定义的,这正是您在这里看到的 .

  • 0

    C是按值调用的 . 如果你调用 freeString(anotherFunction(theString)) 会被设置为 NULL

    如果要让函数对该指针的引用具有副作用,则必须传入指向指针的指针 .

    惯用语C99只会在 freeString() 中省略 str = NULL 的赋值 .

  • 4

    实际上谁必须传递参数的指针而不仅仅是指针的地址

    void freeString( struct String **str)
    {
      ...
      *str=NULL;
    }
    

    否则你将指针str的副本设置为NULL而不是str本身...

    并进入main()不要忘记测试NULL指针以避免崩溃:

    if (theString!=NULL)
      printf("\nData: %s", theString->value);
    
  • 0

    您正在尝试访问已发布的字段 . 这导致了不确定的行为 . 尽管在某些编译器上发布了该值,您仍然可以访问该值,因为该特定字段不会被任何其他正在运行的应用程序重置 . 即使在X-Code上,这也很愉快,但在Visual Studio Compiler上却没有 .

相关问题