为什么 Windows 日文语言环境使子进程 getenv return 的值与 putenv 的值不同?
Why does Windows Japanese locale make child process getenv return different value than was put with putenv?
当 Windows system locale 是日语时,为什么子进程的 getenv 结果与父进程的 putenv 中使用的值不完全匹配?
如果我的变量值未使用有效字符,是否有一系列有效的十六进制值保证对所有 Windows 系统局部变量的环境变量有效?
当语言环境设置为 "English (United States)" 时,下面的示例程序显示了此行为:
$ ./test.exe 1
parent: expected 13, got 13
child: expected 13, got 13
当系统区域设置为 "Japanese (Japan)" 时,相同的程序(未重新编译)显示不同的行为:
$ ./test.exe 1
parent: expected 13, got 13
child: expected 13, got 45
前 5 个字符匹配,但第 6 个和第 7 个字符不匹配。
这是示例程序。我在取消选择 "Precompiled header"、取消选择 "Security Development Lifecycle checks"、选择 "Empty Project" 并将以下内容添加为 [=37] 时使用默认的 Visual Studio 2012 "Win32 Console Application" 新项目设置进行编译=] 在 "Source Files" 下。我是运行Windows7.
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <string>
int main(int argc, char* argv[])
{
const int index_6_value = 0x13;
std::string label = argc == 2 ? "parent" : " child";
const char name[] = { 0x73 /*s*/, 0 };
char* before_insert = getenv(name);
if ( argc == 1 && before_insert != 0) std::cout << label << ": expected " << std::hex << index_6_value << ", got " << int(before_insert[6]) << std::endl;
if (argc > 1)
{
// 0 1 2 3 4 5 6 7
char put_arg[] = { 0x73/*s*/, 0x3D/*=*/, 0x49, 0x73, 0xb0, 0xf6, 0xe3, 0x87, 0x13, 0 };
putenv(put_arg);
char* after_insert = getenv(name);
if (after_insert) std::cout << label << ": expected " << std::hex << index_6_value << ", got " << int(after_insert[6]) << std::endl;
std::string command = std::string("\"") + argv[0] + "\"";
std::system(command.c_str());
}
return 0;
}
putenv 变量值应限制为可打印的 ASCII 值,否则 Windows 可能无法正确保留值,具体取决于本地。这没有很好地记录,但这个想法可能是为了避免双字节局部变量中的无效多字节序列,你可以看到可打印的 ASCII 值(0x20-0x7E)在所有代码页:
https://msdn.microsoft.com/en-us/goglobal/bb964654
跨平台和跨本地环境变量使用来存储任意字节很难正确执行,应该避免。
当 Windows system locale 是日语时,为什么子进程的 getenv 结果与父进程的 putenv 中使用的值不完全匹配?
如果我的变量值未使用有效字符,是否有一系列有效的十六进制值保证对所有 Windows 系统局部变量的环境变量有效?
当语言环境设置为 "English (United States)" 时,下面的示例程序显示了此行为:
$ ./test.exe 1
parent: expected 13, got 13
child: expected 13, got 13
当系统区域设置为 "Japanese (Japan)" 时,相同的程序(未重新编译)显示不同的行为:
$ ./test.exe 1
parent: expected 13, got 13
child: expected 13, got 45
前 5 个字符匹配,但第 6 个和第 7 个字符不匹配。
这是示例程序。我在取消选择 "Precompiled header"、取消选择 "Security Development Lifecycle checks"、选择 "Empty Project" 并将以下内容添加为 [=37] 时使用默认的 Visual Studio 2012 "Win32 Console Application" 新项目设置进行编译=] 在 "Source Files" 下。我是运行Windows7.
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <string>
int main(int argc, char* argv[])
{
const int index_6_value = 0x13;
std::string label = argc == 2 ? "parent" : " child";
const char name[] = { 0x73 /*s*/, 0 };
char* before_insert = getenv(name);
if ( argc == 1 && before_insert != 0) std::cout << label << ": expected " << std::hex << index_6_value << ", got " << int(before_insert[6]) << std::endl;
if (argc > 1)
{
// 0 1 2 3 4 5 6 7
char put_arg[] = { 0x73/*s*/, 0x3D/*=*/, 0x49, 0x73, 0xb0, 0xf6, 0xe3, 0x87, 0x13, 0 };
putenv(put_arg);
char* after_insert = getenv(name);
if (after_insert) std::cout << label << ": expected " << std::hex << index_6_value << ", got " << int(after_insert[6]) << std::endl;
std::string command = std::string("\"") + argv[0] + "\"";
std::system(command.c_str());
}
return 0;
}
putenv 变量值应限制为可打印的 ASCII 值,否则 Windows 可能无法正确保留值,具体取决于本地。这没有很好地记录,但这个想法可能是为了避免双字节局部变量中的无效多字节序列,你可以看到可打印的 ASCII 值(0x20-0x7E)在所有代码页:
https://msdn.microsoft.com/en-us/goglobal/bb964654
跨平台和跨本地环境变量使用来存储任意字节很难正确执行,应该避免。