结构中的字符数组-不续订
Char array in a struct - not renewing?
我有一个for循环,每次都在堆栈上创建一个结构的新实例。这个结构只包含2个变量-2个64字节的字符数组。
代码如下:
for (std::map<std::string, std::string>::iterator iter = m_mDevices.begin(); iter != m_mDevices.end(); ++iter)
{
Structs::SDeviceDetails sRecord;
if (false == GenerateDeviceCacheRecord(iter->first, iter->second, sRecord)) // could just pass iter in?
{
// Failed to create cache record
return false;
}
}
我在调试器中看到的真正奇怪的事情是,每次循环时,我都会在sRecord的缓冲区中看到相同的值。即sRecord.m_strUsername和sRecord.m-strPassword被"重写",而不是新创建的结构。
如果在第一轮循环中,sRecord.m_strUsername是"abc",那么在GenerateDeviceCacheRecord函数(它只是修改sRecord)之后,sRecord.ms_strUsername可能是"HIc",其中c是第一次循环中的字符!很明显,我期待的是"abc"answers"HI",而不是"abc"answers"HIc"。有人知道这里可能发生了什么吗?
感谢
额外代码:
namespace Constants
{
static const int64 MAX_HOSTNAME_BUFFER = 64;
static const int64 MAX_ILA_BUFFER = 64;
};
struct SDeviceRecordDetails
{
char m_strHostname[Constants::MAX_HOSTNAME_BUFFER];
char m_strILA[Constants::MAX_ILA_BUFFER];
};
bool GenerateDeviceCacheRecord(std::string strHostname, std::string strILA, Structs::SDeviceRecordDetails& sRecord)
{
// Convert strings to char arrays to store in the authentication cache manager records
if (strHostname.length() > Constants::MAX_HOSTNAME_BUFFER)
return false;
if (strILA.length() > Constants::MAX_ILA_BUFFER)
return false;
std::copy(strHostname.begin(), strHostname.end(), sRecord.m_strHostname);
std::copy(strILA.begin(), strILA.end(), sRecord.m_strILA);
return true;
}
//! @brief Devices retrieved from XML file
std::map<std::string, std::string> m_mDevicesAuthenticated;
所以。我很感激你试图接近一个更好的问题。因此,我将与您一起采取下一步行动。
你发布的并不是真正的mcve
以下是您的问题的解决方案:
#include <iostream>
#include <cstdint>
#include <map>
#include <string>
#include <algorithm>
namespace Constants
{
static const int64_t MAX_HOSTNAME_BUFFER = 64;
static const int64_t MAX_ILA_BUFFER = 64;
};
struct SDeviceRecordDetails
{
char m_strHostname[Constants::MAX_HOSTNAME_BUFFER];
char m_strILA[Constants::MAX_ILA_BUFFER];
};
bool GenerateDeviceCacheRecord(std::string strHostname, std::string strILA, SDeviceRecordDetails& sRecord)
{
// Convert strings to char arrays to store in the authentication cache manager records
if (strHostname.length() > Constants::MAX_HOSTNAME_BUFFER)
return false;
if (strILA.length() > Constants::MAX_ILA_BUFFER)
return false;
std::copy(strHostname.begin(), strHostname.end(), sRecord.m_strHostname);
std::copy(strILA.begin(), strILA.end(), sRecord.m_strILA);
return true;
}
std::map<std::string, std::string> m_mDevices;
int main() {
m_mDevices["hello"] = "foo";
m_mDevices["buzz"] = "bear";
for (std::map<std::string, std::string>::iterator iter = m_mDevices.begin(); iter != m_mDevices.end(); ++iter) {
SDeviceRecordDetails sRecord;
const bool result = GenerateDeviceCacheRecord(iter->first, iter->second, sRecord);
if (result == false)
std::cout << "Failedn";
else
std::cout << sRecord.m_strHostname << " " << sRecord.m_strILA << "n";
}
}
需要注意的事项:
- 我可以照原样(而不是你的问题中的两个代码块),然后把它扔给编译器
- 我包含了正确的
#include
行 - 您的类型名称中存在代码中未表示的命名空间
m_mDevicesAuthenticated
!=m_mDevices
- 您没有包含任何实际有任何输出的内容
m_mDevices
中的实际内容是什么?这真的很重要- 在其他一些小的修改中,我必须应用到代码中才能构建它
这个代码做了什么
此代码几乎产生正确的输出。它有一个错误,写入sRecord
的字符串不是以null结尾的。
由于编译器是如何生成代码的,并且您没有明确地清除每个循环的sRecord
,所以这很可能是问题的根本原因。
让我们解决这个问题:
代替:
std::copy(strHostname.begin(), strHostname.end(), sRecord.m_strHostname);
std::copy(strILA.begin(), strILA.end(), sRecord.m_strILA);
让我们做:
snprintf(sRecord.m_strHostname, Constants::MAX_HOSTNAME_BUFFER, "%s", strHostname.c_str());
snprintf(sRecord.m_strILA, Constants::MAX_ILA_BUFFER, "%s", strILA.c_str());
或者您可能关心sRecord
在每个循环开始时使用的内容:
在这种情况下,sRecord
在每个循环开始时都不会被初始化。出于优化目的,编译器可以在结构中自由包含垃圾数据。
碰巧大多数编译器都会将结构的每次迭代放在内存中完全相同的位置。这意味着结构中的垃圾数据可能是上一次迭代中的数据。或者其他一些垃圾,这取决于编译器优化的功能。
您可以通过初始化结构以包含显式数据来修复此问题:
SDeviceRecordDetails sRecord = {};
这一切看起来是什么样子的:
完成的代码,所有的错误修复看起来像:
#include <iostream>
#include <cstdint>
#include <map>
#include <string>
#include <algorithm>
namespace Constants
{
static const int64_t MAX_HOSTNAME_BUFFER = 64;
static const int64_t MAX_ILA_BUFFER = 64;
};
struct SDeviceRecordDetails
{
char m_strHostname[Constants::MAX_HOSTNAME_BUFFER];
char m_strILA[Constants::MAX_ILA_BUFFER];
};
bool GenerateDeviceCacheRecord(std::string strHostname, std::string strILA, SDeviceRecordDetails& sRecord)
{
// Convert strings to char arrays to store in the authentication cache manager records
if (strHostname.length() > Constants::MAX_HOSTNAME_BUFFER)
return false;
if (strILA.length() > Constants::MAX_ILA_BUFFER)
return false;
snprintf(sRecord.m_strHostname, Constants::MAX_HOSTNAME_BUFFER, "%s", strHostname.c_str());
snprintf(sRecord.m_strILA, Constants::MAX_ILA_BUFFER, "%s", strILA.c_str());
return true;
}
std::map<std::string, std::string> m_mDevices;
int main() {
m_mDevices["hello"] = "foo";
m_mDevices["buzz"] = "bear";
m_mDevices["zed"] = "zoo";
for (std::map<std::string, std::string>::iterator iter = m_mDevices.begin(); iter != m_mDevices.end(); ++iter) {
SDeviceRecordDetails sRecord = {};
const bool result = GenerateDeviceCacheRecord(iter->first, iter->second, sRecord);
if (result == false)
std::cout << "Failedn";
else
std::cout << sRecord.m_strHostname << " " << sRecord.m_strILA << "n";
}
}
输出:
buzz bear
hello foo
zed zoo
这在我看来是正确的。
我在这里没有看到任何初始化。你看到的是以前发生在内存中那个位置的东西,对你来说,今天,恰好是这些数据成员以前的内容。
- 指向指向字符数组的指针数组的指针
- 比较字符数组
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- 使用无符号字符数组有效存储内存
- 按字符值访问int数组
- 错误:字符数组的初始值设定项太多
- 对字符数组中的元素执行逐位操作
- C++,在int数组中输入字符串或字符会输出0,而不是ascii或error
- C++ 无法在字符数组中使用 for 循环打印字母模式
- 如何在 C++ 中从文件中读取字符数组(带有一些空格)
- 移动二维数组中的字符
- C++ 传递二维字符数组
- 无法在 C++ 中输入字符数组
- C++ 带结构的数组字符
- 数组字符包含量超出预期
- 读取文件并添加到数组字符
- 如何在Qt中更改或替换数组字符
- 为什么编译器不在参数中传递数组字符 *arr[] 的大小?
- 井字棋数组字符错误
- 分割数组字符