【问题标题】:Debugging parameter corruption in C++?在 C++ 中调试参数损坏?
【发布时间】:2011-01-02 07:41:11
【问题描述】:

我的项目中有一个插件系统(在 linux 上运行),部分原因是插件有一个“运行”方法,例如:

void run(int argc, char* argv[]);

我正在调用我的插件并检查我的 argv 数组(在做了很多其他事情之后),并且 阵列已损坏。我可以在函数顶部打印出这些值,它们是正确的,但在稍后的执行中就不行了。显然有些东西正在破坏堆,但是 我不知道如何尝试准确确定覆盖该记忆的内容。 Valgrind 对我帮助不大。

请求的示例代码:

我的插件看起来像这样:

void test_fileio::run(int argc, char* argv[]) {
  bool all_passed = true;

  // Prints out correctly.
  for (int ii=0; ii < argc; ii++) {
    printf("Arg[%i]: %s\n", ii, argv[ii]);
  }

  <bunch of tests snipped for brevity>

  // Prints out inccorrectly.
  for (int ii=0; ii < argc; ii++) {
    printf("Arg[%i]: %s\n", ii, argv[ii]);
  }
}

这被链接到一个将它公开给 python 的系统,所以我可以将这些插件称为 python 函数。所以我将一个字符串参数带到我的 python 函数中,然后将其分解出来:

char** translate_arguments(string args, int& argc) {
  int counter = 0;
  vector<char*> str_vec;

  // Copy argument string to get rid of const modifier
  char arg_str[MAX_ARG_LEN];
  strcpy(arg_str, args.c_str());

  // Tokenize the string, splitting on spaces
  char* token = strtok(arg_str, " ");
  while (token) {
    counter++;
    str_vec.push_back(token);
    token = strtok(NULL, " ");
  }

  // Allocate array
  char** to_return = new char*[counter];
  for (int ii=0; ii < counter; ii++)
    to_return[ii] = str_vec[ii];

  // Save arg count and return
  argc = counter;
  return to_return;
}

然后将生成的 argc 和 argv 传递给上面提到的插件。

【问题讨论】:

  • 您能否提供一个代码示例,以便我们的 SO 用户更容易理解您在做什么?
  • 添加了示例代码,它是骨架,因为这个插件非常大,但这可以让您了解问题所在。
  • 我认为我们可以判断问题的本质是什么,但您忽略了任何有助于确定问题实际根源的内容。有一百万种不同的东西可能会破坏这个数组,但你已经忽略了所有的代码。
  • 该死的...留下的OP海报...应该被标记为作业......
  • 抱歉,源代码太大,无法完整发布。我主要是在寻找有关如何调试这类事情的提示,而不是在这种情况下寻找具体的帮助。

标签: c++ heap-memory heap-corruption


【解决方案1】:

查看如何在调试器中使用内存访问断点。如果您有可靠的回购,这将在几秒钟内查明您的问题。在windbg中是:

ba w4 0x<address>

ba 代表“访问中断”,“w4”代表“写入 4 个字节”(在 64 位系统上使用 w8),“地址”显然是您看到的已损坏地址。 gdb 和 Visual Studio 具有相似的功能。

【讨论】:

【解决方案2】:

translate_arguments 是如何被调用的?那是缺少的...

由于run 函数有参数char *argv[],它在调用插件中的run 函数之前是否准备了一个指向字符的指针数组?

这看起来像是造成问题的那一行……从代码来看

// 分配数组 char** to_return = new char*[计数器];

你打算分配一个指向chars的指针,一个double指针,但是看起来代码的优先级有点搞混了? 你有没有试过这样:

char** to_return = new (char *)[counter];

另外,在您的 for 循环中,如图所示...您没有为向量中包含的字符串本身分配空间...?

for (int ii=0; ii

由于 OP 没有显示如何调用 translate_arguments 并且缺乏更多信息,因此可能会被否决……并且误判我的答案是否不正确……

希望这会有所帮助, 最好的祝福, 汤姆。

【讨论】:

  • 我同意您的第二部分(为字符串分配存储空间)。如当前所写,向量中的指针指向存储在堆栈上的数据,然后超出范围(arg_str)。调用 translate_arguments 后,可能有一些代码最终会覆盖堆栈中的该空间(局部变量等)。
【解决方案3】:

如果 valgrind 和代码检查对您没有帮助,您可以尝试使用电子围栏

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-13
    • 1970-01-01
    • 1970-01-01
    • 2020-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多