valgrind 发现错误将指针传递给函数,但当代码在同一范围内时没有错误

valgrind finds errors passing pointer to function, but no errors when the code is in the same scope

我想知道为什么在此示例代码中,valgrind 没有发现任何错误或丢失的记忆:

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

int main()
{
   char *str;

   /* Initial memory allocation */
   str = (char *) malloc(8);
   strcpy(str, "example");
   printf("String = %s,  Address = %u\n", str, str);

   /* Reallocating memory */
   str = (char *) realloc(str, 14);
   strcat(str, ".com");
   printf("String = %s,  Address = %u\n", str, str);

   free(str);

   return(0);
}

但是,当我用函数替换这些行时:

int main() {
   ...
   /* Reallocating memory */
   newstr(str);
   ...
}

void newstr(char *str) {
   str = (char *) realloc(str, 14);
   strcat(str, ".com");
}

我在 valgrind 上收到 19 个错误,主要是关于无效读取的抱怨。然而,程序执行和输出的一切都是一样的,没有错误。当我将 str 传递给 valgrind 通知我的内存中发生的函数时,是否发生了什么?我该怎么做才能解决这个问题?我如何才能更多地了解此行为及其影响?

这是两种情况下程序的输出:

String = example,  Address = 16445456
String = example.com,  Address = 16445456

valgrind 抱怨读取正确,你从无效内存中读取。您从 str 的无效值中读取。 更正以下代码。

int main() {
   ...
   /* Reallocating memory */
   str = newstr(str);
   ...
}

char * newstr(char *str) {
   str = (char *) realloc(str, 25);
   strcat(str, ".com");
   return str;
}

作为一般规则,传递给 C 函数的参数按值传递。除非你显式地通过引用传递,或者传递一个指向你的对象的指针,否则在函数 returns 时,被调用函数中所做的更改将不会持续存在。

在你的情况下,你可能正在传递一个指针,但你试图在函数中修改指针而不是修改指针引用的内容。

除了在 return 新指针的另一个答案中提供的解决方案外,您还有两个选择:

指向指针的指针

void newstr(char **str) {
   *str = (char *) realloc(*str, 25);
   strcat(*str, ".com");
}

参考

void newstr(char *&str) {
   str = (char *) realloc(str, 25);
   strcat(str, ".com");
}

通过引用传递,除其他外,您可以更改函数内的引用值。你可以用一个指针来做到这一点

但是在

void newstr(char *str) {
   str = (char *) realloc(str, 25); <-- changed the pointer
   strcat(str, ".com"); 
}

函数内部改变的值是指针。因此,您必须通过引用传递指针(或 return BayK 所示的更改后的指针)

void newstr(char *& str) {
   str = (char *) realloc(str, 25);
   strcat(str, ".com");
}

或者您可以拥抱这种全副武装且可操作的 C++ 编程语言的强大功能,并使用 std::string

#include <iostream>
#include <string>
int main()
{
    std::string str = "example";

    std::cout << "String = " << str << ",  Address = "  << &str << "\n";
    str += ".com";
    std::cout << "String = " << str << ",  Address = "  << &str << "\n";
    return(0);
}