我有一个for循环,我每次都在堆栈上创建一个结构的新实例。该结构仅包含2个变量-2个64字节的char数组。

代码如下:

        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.m_strUsername可能为“ HIc”,其中c是第一个循环以外的字符!我显然希望“ abc”和“ HI”,而不是“ abc”和“ 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。

这是您的问题的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 << "Failed\n";
        else
            std::cout << sRecord.m_strHostname << " " << sRecord.m_strILA << "\n";
    }
}


注意事项:


我可以直接使用它(而不是您的问题中的两个代码块),然后将其扔给编译器。
我包括正确的#include行。
您的类型名称中有一些名称空间未在代码中表示。
m_mDevicesAuthenticated!= m_mDevices
您没有包含实际上有任何输出的任何内容。
m_mDevices中实际上是什么?这一点非常重要!
在其他一些小的更正中,我不得不将其应用于代码以使其得以构建。


这段代码是做什么的?

此代码几乎可以产生正确的输出。它有一个错误,因为写入sRecord的字符串不是空终止的。

由于编译器生成代码的方式,并且您没有明确清除每个循环的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 << "Failed\n";
        else
            std::cout << sRecord.m_strHostname << " " << sRecord.m_strILA << "\n";
    }
}


并输出:

buzz bear
hello foo
zed zoo


在我看来,这看起来很正确。

关于c++ - 结构中的Char数组-不更新吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28461998/

10-10 02:39