c++ - 两次调用函数会产生段错误(与 char* 到字符串的转换有关)
问题描述
我想"%LOCALAPPDATA%/test.txt"
用 Windows 环境路径扩展一个字符串 ( )。以下函数原则上可以完成这项工作,但是使用相同的输出字符串再次调用它(或在调用函数之前为输出字符串分配一些值)会产生段错误。
char*
显然,通过转换为,我犯了一些(可能非常糟糕)错误std::string
,但我真的不明白这里发生了什么(除了一些内存地址稍后不可用的事实之外)。
#include "processenv.h"
void expandWindowsString(const std::string &input, std::string &output)
{
const char* in = input.c_str();
char* out;
ExpandEnvironmentStrings(in, out, 1024);
output = out;
}
int main(int argc, char *argv[])
{
std::string path;
expandWindowsString("%LOCALAPPDATA%/test.txt", path);
std::cout << "path is " << path << std::endl;
//works fine so far, but if I execute the function again (with 'path') or initialising path beforehand with std::string path = "", a segfault occurs.
expandWindowsString("%LOCALAPPDATA%/test.txt", path); // commenting out this line, makes the code work.
std::cout << "path is " << path << "\n";
}
解决方案
正如文档所解释的:
lpDst
一个指向缓冲区的指针,它接收在lpSrc缓冲区中展开环境变量字符串的结果。
缓冲区需要由调用者提供,而代码只是传递一个未初始化的指针,同时诱使系统相信它指向大小为 1024 字节的内存。
一个简单的解决方法是:
void expandWindowsString(const std::string &input, std::string &output)
{
const char* in = input.c_str();
char out[1024];
ExpandEnvironmentStrings(in, out, 1024);
output = out;
}
有很大的改进空间,例如
- 使用Unicode 版本
- 处理错误(如文档中所述)
- 重复增长输出缓冲区以防 API 调用返回的值大于提供的缓冲区长度
std::string
使用指针和长度构造 a- 返回一个值而不是使用 out 参数
至于为什么第二次调用失败:这是一个毫无意义的问题。代码通过写入未初始化的指针表现出未定义的行为。这样,任何结果都是可能的,包括看起来像预期工作的代码。
推荐阅读
- git-tower - 我可以使用 Git Tower 获取单个远程分支吗?
- ubuntu - 无法将 https://www.example.com 重定向到 https://example.com
- swift - 在 KeyWindow 上将 XIB 显示为 UIView
- javascript - 如何循环遍历数组以将 html 分配给工具提示
- mediawiki - MediaWiki 获取字符串的第一个字母
- r - 如何合并具有共同主题 ID 列和其他列中许多不同变量的多个 CSV 文件?输入
- jquery - 在 Django 应用程序中使用 JQuery 提交 HTML 表单
- excel - 不同的计算机以不同的方式处理“On Error Resume Next”?
- c# - 在 App Xamarin 表单之外创建弹出窗口
- python - 如何在 TradingView Pine-Script 中运行条件语句?