Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从const char*或LPCSTR生成std::字符串时数据丢失_C++_String_Pointers_C++11 - Fatal编程技术网

C++ 从const char*或LPCSTR生成std::字符串时数据丢失

C++ 从const char*或LPCSTR生成std::字符串时数据丢失,c++,string,pointers,c++11,C++,String,Pointers,C++11,我有一个返回LPSTR/const char*的函数,需要将其转换为std::string。我就是这样做的 std::string szStr(foo(1)); 当foo返回一个32个字符长的字符串时,它在所有情况下都能正常工作,但失败了。通过这种方法,我得到了“。所以我认为它和长度有关。所以我改变了一点 std::string szStr(foo(1) , 32); 这给了我“0” 然后我尝试了另一种乏味的方法 const char * cstr_a = foo(1); const cha

我有一个返回LPSTR/const char*的函数,需要将其转换为std::string。我就是这样做的

std::string szStr(foo(1));
当foo返回一个32个字符长的字符串时,它在所有情况下都能正常工作,但失败了。通过这种方法,我得到了
。所以我认为它和长度有关。所以我改变了一点

std::string szStr(foo(1) , 32);
这给了我
“0”

然后我尝试了另一种乏味的方法

const char * cstr_a = foo(1);
const char * cstr_b = foo(2);

size_t ln_a = strlen(cstr_a);
size_t ln_b = strlen(cstr_b);

std::string szStr_a( cstr_a , ln_a );
std::string szStr_b( cstr_b , ln_b );
但奇怪的是,在这个方法中,两个指针都得到了相同的值,即foo(1)应该返回abc,foo(2)应该返回xyz。但这里cstr_a首先得到abc,但当cstr_b得到xyz时,cstr_a和cstr_b的值都变成xyz。我对此感到茫然和困惑

是的,我不能使用std::wstring

什么是foo?

foo基本上是从注册表读取一个值,并将其作为LPSTR返回。现在我需要读取的注册表中的一个值是MD5哈希字符串(32个字符),这就是它失败的地方

实际的Foo函数:

LPCSTR CRegistryOperation::GetRegValue(HKEY hHeadKey, LPCSTR szPath, LPCSTR szValue)
{
    HKEY hKey;
    CHAR szBuff[255] = ("");
    DWORD dwBufSize = 255;

    ::RegOpenKeyEx(hHeadKey, (LPCSTR)szPath, 0, KEY_READ, &hKey);
    ::RegQueryValueEx(hKey, (LPCSTR)szValue, NULL, 0, (LPBYTE)szBuff, &dwBufSize);
    ::RegCloseKey(hKey);

    LPCSTR cstr(szBuff);

    return cstr;
}
StrResultMap RegValues;
std::string lid(CRegistryOperation::GetRegValue(HKEY_CURRENT_USER, REG_KEY_HKCU_PATH, "LicenseID"));
std::string mid(CRegistryOperation::GetRegValue(HKEY_CURRENT_USER, REG_KEY_HKCU_PATH, "MachineID"), 32);
std::string vtill(CRegistryOperation::GetRegValue(HKEY_CURRENT_USER, REG_KEY_HKCU_PATH, "ValidTill"));
std::string adate(CRegistryOperation::GetRegValue(HKEY_CURRENT_USER, REG_KEY_HKCU_PATH, "ActivateDT"));
std::string lupdate(CRegistryOperation::GetRegValue(HKEY_CURRENT_USER, REG_KEY_HKCU_PATH, "LastUpdate"));

RegValues["license_id"] = lid;
RegValues["machine_id"] = mid;
RegValues["valid_till"] = vtill;
RegValues["activation_date"] = adate;
RegValues["last_updated"] = lupdate;
原始演员代码:

LPCSTR CRegistryOperation::GetRegValue(HKEY hHeadKey, LPCSTR szPath, LPCSTR szValue)
{
    HKEY hKey;
    CHAR szBuff[255] = ("");
    DWORD dwBufSize = 255;

    ::RegOpenKeyEx(hHeadKey, (LPCSTR)szPath, 0, KEY_READ, &hKey);
    ::RegQueryValueEx(hKey, (LPCSTR)szValue, NULL, 0, (LPBYTE)szBuff, &dwBufSize);
    ::RegCloseKey(hKey);

    LPCSTR cstr(szBuff);

    return cstr;
}
StrResultMap RegValues;
std::string lid(CRegistryOperation::GetRegValue(HKEY_CURRENT_USER, REG_KEY_HKCU_PATH, "LicenseID"));
std::string mid(CRegistryOperation::GetRegValue(HKEY_CURRENT_USER, REG_KEY_HKCU_PATH, "MachineID"), 32);
std::string vtill(CRegistryOperation::GetRegValue(HKEY_CURRENT_USER, REG_KEY_HKCU_PATH, "ValidTill"));
std::string adate(CRegistryOperation::GetRegValue(HKEY_CURRENT_USER, REG_KEY_HKCU_PATH, "ActivateDT"));
std::string lupdate(CRegistryOperation::GetRegValue(HKEY_CURRENT_USER, REG_KEY_HKCU_PATH, "LastUpdate"));

RegValues["license_id"] = lid;
RegValues["machine_id"] = mid;
RegValues["valid_till"] = vtill;
RegValues["activation_date"] = adate;
RegValues["last_updated"] = lupdate;
请帮我克服它。
谢谢。

函数返回指向
GetRegValue
堆栈帧中缓冲区的指针。这不起作用:在
GetRegValue
终止后,指针
cstr
指向堆栈中某个未定义的值。尝试将
szBuff
设置为静态,看看是否有帮助

LPCSTR CRegistryOperation::GetRegValue(HKEY hHeadKey, LPCSTR szPath, LPCSTR szValue)
{
    HKEY hKey;
  //Here:
    static CHAR szBuff[255] = ("");
    szBuff[0]=0;
    DWORD dwBufSize = 255;

    ::RegOpenKeyEx(hHeadKey, (LPCSTR)szPath, 0, KEY_READ, &hKey);
    ::RegQueryValueEx(hKey, (LPCSTR)szValue, NULL, 0, (LPBYTE)szBuff, &dwBufSize);
    ::RegCloseKey(hKey);

    LPCSTR cstr(szBuff);

    return cstr;
}
更新:我没有强制要求返回std::string或传入缓冲区,因为那样会更改接口。将指针返回到静态缓冲区是一种常见的习惯用法,如果返回的指针值的生存期限制在几个范围内(如从缓冲区值构建std::string),则大多数情况下是没有问题的

多线程并不是真正的问题,因为几乎每个编译器现在都有某种形式的线程本地存储支持<代码>\uuu declspec(线程)静态字符szBuff[255]=(“”)应该适用于Microsoft编译器,而gcc则适用于线程。C++11甚至为此提供了一个新的存储类说明符(
thread\u local
)。不过,您不应该从信号处理程序调用GetRegValue,但这没关系——无论如何,您也不能在那里做太多的事情(例如,从堆中分配内存!)

更新:评论者认为,我不应该建议这样做,因为当再次调用GetRegValue时,指向静态缓冲区的指针将指向无效数据。虽然这显然是正确的,但我认为以此作为论据是错误的。为什么?看看这些例子:

  • 从strdup()返回的指针在free()之前有效
  • 指向使用new创建的内容的指针在删除之前是有效的
  • 只要字符串没有修改,从string::c_str()返回的常量字符*就有效
  • 如果删除了std::vector中的元素,则std::vector迭代器无效
  • 如果删除了std::vector中的元素,则std::list迭代器仍然有效,除非它指向已删除的元素
  • 从GetRegValue返回的指针在再次调用GetRegValue之前是有效的
  • std::ifstream在以下情况下有效:…您知道,good()、fail()等等

说“看,如果你不够小心,事情就会变得无效”是没有意义的,因为编程不是粗心大意。我们正在处理对象,这些对象具有有效或无效的条件,如果对象具有定义良好的有效或无效条件,那么我们可以编写具有定义良好行为的程序。返回指向静态缓冲区(即线程本地)的指针具有定义良好的含义,开发人员可以使用它编写定义良好的程序。当然,除非说开发人员疏忽大意或懒得阅读例行程序的文档

> P>作为北欧主机的ANWSER的补充,从C或C++函数返回3种常用缓冲区的方法有:

  • 使用静态缓冲区-简单而漂亮,直到出现重入问题(多线程或递归性)
  • 将缓冲区作为输入参数传递,只需返回写入缓冲区的字符数-如果缓冲区的大小确实是常量,则返回ok
  • malloc函数中的缓冲区(它在堆中而不在堆栈中),并以闪烁的红色记录调用者必须释放它

<>但是,当你把问题标记为C++时,你可以在函数中创建STD::string并返回它。C++函数允许返回STD::string,因为不同的操作符(复制构造函数、做作、……)自动地处理分配问题。

< P>可以避免返回一个已经超出范围的指针,返回一个<代码> STD::String 。
std::string CRegistryOperation::GetRegValue(HKEY hHeadKey, LPCSTR szPath, LPCSTR szValue)
{
    HKEY hKey = 0;
    CHAR szBuff[255] = { 0 };
    DWORD dwBufSize = sizeof(szBuf);

    if (::RegOpenKeyEx(hHeadKey, (LPCSTR)szPath, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
        ::RegQueryValueEx(hKey, (LPCSTR)szValue, NULL, 0, (LPBYTE)szBuff, &dwBufSize);
        ::RegCloseKey(hKey);
    }
    return std::string(szBuf);
}

那么
foo
到底在做什么?返回的c字符串是否以null结尾?行
std::string szStr(foo(1))foo
返回以零结尾的字符序列,则code>是100%正确的。
foo基本上是在读取
<代码>这就是它失败的地方。
如果这就是它失败的地方(很可能是),那么为什么这个代码不在问题中呢?
LPCSTR
是指针,是吗?它指向一个本地数组,并在函数结束时销毁该数组时悬空。取消引用返回的指针(这是
字符串的构造函数所做的)具有未定义的行为。@当您将数组强制转换为指针时,数组参数首先衰减为指向第一个值的指针。因此,您返回的是一个指向
szBuff
的第一个元素的指针,该元素是一个本地数组。使
szBuf
静态的问题是,如果函数被多次调用,并且调用方保留返回的poi