当我调用不相关的方法时,c 字符串的值发生变化
The value of c-strings change when I call an unrelated method
我正在处理一个头文件,该文件定义了一个命名空间,其中定义了一些 c 字符串。
namespace env {
const char* C_NAME;
const char* SYS_DRIVE;
const char* PROCESSOR;
const char* PROCESSOR_ARCHITECTURE;
const char* OSNAME;
}
我的主要功能如下所示:
int main(int argc, char* argv[], char* env[]) {
initialize_environment_vars(env);
cout << "C_NAME\t\t\t" << env::C_NAME << endl;
/*...*/
return 0;
}
我的问题是我在 initialize_environment_vars()
中初始化的字符串没有我想要的值。
void initialize_environment_vars(char* env[]) {
int id = PRIVATE::findEntry(env, "COMPUTERNAME");
env::C_NAME = (str::getAfter(env[id], "=")).c_str(); // getAfter() returns a string
//std::cout << env::C_NAME << std::endl; //Right value!!!
id = PRIVATE::findEntry(env, "SystemDrive");
std::cout << env::C_NAME; //Value at env[id]
/*Here the other constants are initialized in the same way.*/
}
我发现函数 initialize_environment_vars()
中的变量具有正确的值,直到我调用函数 findEntry() 来查找另一个条目。
int PRIVATE::findEntry(const char* const arr[], std::string toFind) {
bool found = false;
int i = 0;
std::string actual;
while(arr[i] && !found) {
actual = arr[i];
if(str::contains(actual, toFind)) {
found = true;
break;
}
i++;
}
if(found)
return i;
else { /*Error message and exit program*/ }
}
看了这篇post,string::c_str query,我还以为我在initialize_environment_vars()
中使用.c_str()
是错误的,因为返回的字符串会被破坏在调用 .c_str()
之后,但这似乎并非如此,因为 env::C_NAME
在 main()
.
中有效
因此我有两个问题:
- 为什么我的
PRIVATE::findEntry(const char* const [], std::string)
函数会按照我上面使用它的方式更改 env::C_NAME
的值,即使它只是 returns 一个 int
并且不修改数组或条目?
- 为什么
env::C_NAME
在 'main()' 中仍然有效? str::getAfter(const std::string&, std::string)
returns 这个字符串的析构函数被调用后不就失效了吗? (已回答)
Why does my PRIVATE::findEntry(const char* const [], std::string) function change the value of env::C_NAME the way I use it above, even though it only returns an int and does not modify the array nor the entries?
如果字符串被破坏或修改,c_str()
的 return 值不再保证有效。
Why is env::C_NAME still valid in 'main()'? Should it not become invalid after the destructor of the string that str::getAfter(const std::string&, std::string) returns is called?
不是。它只是碰巧包含了你想要它包含的东西,而不是碰巧包含了你想要它包含的东西以外的东西。如果您在可能正面朝上的情况下掷硬币,那么您正在做一些错误的事情,但它可能会奏效。如果你再做一次,它可能会发生不起作用。这就是为什么我们不做这样的事情。
不要混淆代码的行为方式与您期望代码的行为方式。在我们期望事情无效的情况下,我们不知道代码的实际行为。它可能碰巧做了一些好事,也可能碰巧做了一些灾难性的事情。它可能会随着编译器选项、编译器版本、平台或其他参数而改变。
您有两个明显的选择。您可以将这些变量的类型从 const char *
更改为 std::string
,或者您可以使用 malloc
或 strdup
分配将保持有效的内存。
您 env
环境中的 "c-strings" 只是指针……仅此而已。例如,env::C_NAME
指向曾经保存您使用 (str::getAfter(env[id], "="))
获得的字符串的地址。谁知道现在那里有什么?您可以将 env
中的 "c-strings" 更改为固定大小的 char
缓冲区,并使用 strcpy()
将内容复制到其中(尽管要小心溢出缓冲区的末尾) ,或者你可以将它们作为指针和 malloc()
space 作为你的字符串副本,然后 strcpy()
将原始字符串放入你的 malloc()
ed 缓冲区,或者最好的选择,使用std::string
不用担心细节问题。
我正在处理一个头文件,该文件定义了一个命名空间,其中定义了一些 c 字符串。
namespace env {
const char* C_NAME;
const char* SYS_DRIVE;
const char* PROCESSOR;
const char* PROCESSOR_ARCHITECTURE;
const char* OSNAME;
}
我的主要功能如下所示:
int main(int argc, char* argv[], char* env[]) {
initialize_environment_vars(env);
cout << "C_NAME\t\t\t" << env::C_NAME << endl;
/*...*/
return 0;
}
我的问题是我在 initialize_environment_vars()
中初始化的字符串没有我想要的值。
void initialize_environment_vars(char* env[]) {
int id = PRIVATE::findEntry(env, "COMPUTERNAME");
env::C_NAME = (str::getAfter(env[id], "=")).c_str(); // getAfter() returns a string
//std::cout << env::C_NAME << std::endl; //Right value!!!
id = PRIVATE::findEntry(env, "SystemDrive");
std::cout << env::C_NAME; //Value at env[id]
/*Here the other constants are initialized in the same way.*/
}
我发现函数 initialize_environment_vars()
中的变量具有正确的值,直到我调用函数 findEntry() 来查找另一个条目。
int PRIVATE::findEntry(const char* const arr[], std::string toFind) {
bool found = false;
int i = 0;
std::string actual;
while(arr[i] && !found) {
actual = arr[i];
if(str::contains(actual, toFind)) {
found = true;
break;
}
i++;
}
if(found)
return i;
else { /*Error message and exit program*/ }
}
看了这篇post,string::c_str query,我还以为我在initialize_environment_vars()
中使用.c_str()
是错误的,因为返回的字符串会被破坏在调用 .c_str()
之后,但这似乎并非如此,因为 env::C_NAME
在 main()
.
因此我有两个问题:
- 为什么我的
PRIVATE::findEntry(const char* const [], std::string)
函数会按照我上面使用它的方式更改env::C_NAME
的值,即使它只是 returns 一个int
并且不修改数组或条目? - 为什么
env::C_NAME
在 'main()' 中仍然有效?str::getAfter(const std::string&, std::string)
returns 这个字符串的析构函数被调用后不就失效了吗? (已回答)
Why does my PRIVATE::findEntry(const char* const [], std::string) function change the value of env::C_NAME the way I use it above, even though it only returns an int and does not modify the array nor the entries?
如果字符串被破坏或修改,c_str()
的 return 值不再保证有效。
Why is env::C_NAME still valid in 'main()'? Should it not become invalid after the destructor of the string that str::getAfter(const std::string&, std::string) returns is called?
不是。它只是碰巧包含了你想要它包含的东西,而不是碰巧包含了你想要它包含的东西以外的东西。如果您在可能正面朝上的情况下掷硬币,那么您正在做一些错误的事情,但它可能会奏效。如果你再做一次,它可能会发生不起作用。这就是为什么我们不做这样的事情。
不要混淆代码的行为方式与您期望代码的行为方式。在我们期望事情无效的情况下,我们不知道代码的实际行为。它可能碰巧做了一些好事,也可能碰巧做了一些灾难性的事情。它可能会随着编译器选项、编译器版本、平台或其他参数而改变。
您有两个明显的选择。您可以将这些变量的类型从 const char *
更改为 std::string
,或者您可以使用 malloc
或 strdup
分配将保持有效的内存。
您 env
环境中的 "c-strings" 只是指针……仅此而已。例如,env::C_NAME
指向曾经保存您使用 (str::getAfter(env[id], "="))
获得的字符串的地址。谁知道现在那里有什么?您可以将 env
中的 "c-strings" 更改为固定大小的 char
缓冲区,并使用 strcpy()
将内容复制到其中(尽管要小心溢出缓冲区的末尾) ,或者你可以将它们作为指针和 malloc()
space 作为你的字符串副本,然后 strcpy()
将原始字符串放入你的 malloc()
ed 缓冲区,或者最好的选择,使用std::string
不用担心细节问题。