【问题标题】:assigning values to structure of a class using class object使用类对象为类的结构赋值
【发布时间】:2013-08-16 12:54:44
【问题描述】:

我遇到了一个非常奇怪的问题。 这是我的代码: 头文件

namespace test
{
class LoadConfigData
{

    struct control_params
    {
         char               active[];
         char               suspended[];
         char               erased[];        
    }*ctrl_params;
bool loadConfig();
};
};

Main.cpp

using namespace std;
using namespace test;
namespace test
{
extern LoadConfigData           *loadConfigDataobj;
LoadConfigData *loadConfigDataobj   = new LoadConfigData;
};
int main()
{
loadConfigDataobj->loadConfig();
cout <<loadConfigDataobj->ctrl_params->active_status_code_v<<endl;
cout <<loadConfigDataobj->ctrl_params->suspended_status_code_v<<endl;
cout <<loadConfigDataobj->ctrl_params->erase_status_code_v<<endl;
return 0;
}

bool LoadConfigData::loadConfig()
{
std::string a = "AC";
std::string b = "SP";
std::string c = "ER";
LoadConfigData::ctrl_params = new LoadConfigData::control_params;
sprintf(loadConfigDataobj->ctrl_params->active,"%s",a.c_str());
sprintf(loadConfigDataobj->ctrl_params->suspended,"%s",b.c_str());
sprintf(loadConfigDataobj->ctrl_params->erased,"%s",c.c_str());
return true;
}

输出:

ER
ER
ER

这意味着它正在为每个结构成员打印最后一个复制的字符串。 我的代码有什么问题。

【问题讨论】:

    标签: c++ class object struct


    【解决方案1】:

    问题是你没有给字符数组一个大小:

    struct control_params
    {
         char               active[];
         char               suspended[];
         char               erased[];        
    }*ctrl_params;
    

    我很惊讶这个编译;我的理解是,未调整大小的数组是不完整的类型,因此不能是非静态类成员。但是,我的编译器至少(可能是您的)将它们视为大小为零的数组,全部位于内存中的同一位置。因此,每次你写一个,它都会覆盖你写给其他人的任何内容。 (当然,行为是未定义的,因为它写入数组边界之外)。

    最简单的解决方案是使用std::string 来表示字符串。这将自动管理它的大小,您可以简单地编写 active = a 而不是乱用 sprintf(或者,稍微更明智的是,strncpy)并希望您不会遇到缓冲区溢出。

    【讨论】:

    • 是的。这是正确的。这是未调整大小的数组的问题。定义大小解决了我的问题。谢谢:)
    • @sajal:你知道自己在做什么吗?你确定弦总是足够大吗?为什么不使用std::string?如果这些确实是配置数据,您可能无法控制输入长度,那么您将遇到任何破解者都会欢迎的安全问题。你对字符串函数漏洞了解多少?请深入阅读en.wikipedia.org/wiki/Software_vulnerabilities,尤其是(但不完全是)关于缓冲区溢出和格式字符串攻击的内容。我真的希望这不是生产代码,只是为了学习。
    • @phresnel:非常感谢您的关注。我在这里提到的代码与我使用的代码不同。我正在从数据库中获取数据,为此我必须使用一个特定的库,该库以 char 数组的形式返回数据,然后将其存储在 control_params 中。我知道字符串的大小,因此它现在可以工作了。但是是的,如果以后字符串大小发生变化,除了更改代码之外,我别无选择。
    • @sajal:您的 DB API 可以改变,它也会改变。那时您将忘记您的 char 数组。如果程序出现段错误,你会很幸运。但它可能会运行数月,并且只有在您最盛大的盛宴上,它才会突然出现段错误,并花费您的金钱和声誉。最好从一开始就使用字符串。
    【解决方案2】:

    问题在于您对sprintf 的使用。 sprintf 不会为您分配任何内存,activesuspendederased 指向奇怪和未定义的地址。您正在调用未定义的行为。

    不添加所有通常必要的细节,使用std::string,它是运算符重载。对于简单的解析,请使用流。目前,完全避免使用任何 C 字符串函数,而只使用 C++。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-08
      相关资源
      最近更新 更多