2

我正在尝试在 Visual C++ 2008 中进行一些经典的 C 开发,它将修改字符串的字符,如下所示:

void ModifyString(char *input)
{
  // Change first character to 'a'
  *input = 'a';
}

当我尝试更改角色时,我遇到了未处理的异常。似乎我可以在 Visual Studio 6 或使用 gcc 中做到这一点,但也许我只是忘记了一些事情。Visual Studio 是否以某种方式按值传递 char* (管理内存)。如果是这样,我该如何关闭它?

4

4 回答 4

8

您可能在某处传递了一个字符串文字:

ModifyString("oops");  // ERROR!

C 和 C++ 允许您从字符串文字(类型为const char[])隐式转换为char*,但不推荐使用这种用法。字符串常量允许在只读内存中分配(通常是这样),因此如果您尝试修改它们,您将遇到访问冲突(也称为分段错误或总线错误)。如果编译器不将字符串常量放入只读内存,程序仍然可以工作,但这是未定义的行为。

正确的做法是将字符串复制到可写缓冲区中:

// one way:
char mystring[] = "test";
ModifyString(mystring);  // ok

// another way:
char mystring[64];  // make sure this is big enough!!
strcpy(mystring, "test");
ModifyString(mystring);  // ok
于 2009-07-11T17:45:40.083 回答
1

输入是字符串文字吗?这大概就是问题所在。否则,您将需要发布更多代码,因为指针最终以某种方式指向内存中的只读位置。

于 2009-07-11T17:38:02.847 回答
1

如果不看 ModifyString 是如何被调用的,就不可能回答这个问题。该函数本身是正确的,假设它的合约将被传递一个非 NULL 值。

但是,呼叫站点可能会通过执行任意数量的操作而失败

  • 传递 NULL
  • 通过邪恶的演员传递 const char
于 2009-07-11T17:38:20.020 回答
0

我不能确切地说为什么这不起作用,但问题出在您的代码中,而不是 Visual Studio。出于某种原因,您向函数传递了一个无效的指针。它要么是空指针,要么指向您无权读取的某个地址。

如果您发布更多代码(函数从哪里调用,以及它是如何调用的?),我们也许能够指出确切的问题。

它在 GCC 或 VC6 中工作的原因很简单,因为它是未定义的行为。C++ 标准并没有说“这应该工作”或“这应该导致崩溃”。如果您写入您无权访问的内存,任何事情都可能发生。根据编译器和运行应用程序的系统,最终访问的地址会有所不同。幸运的是,您在使用 VC2008 编译时遇到了导致访问冲突的地址。在 GCC 和 VC6 下,你就没有那么幸运了,得到了似乎可以工作的代码,只是写了一些垃圾地址。

于 2009-07-11T17:46:40.393 回答