【问题标题】:Why do I get a seg fault when assigning a string pointer to a string pointer?为什么将字符串指针分配给字符串指针时会出现段错误?
【发布时间】:2021-11-21 16:19:38
【问题描述】:

考虑以下简化代码:

typedef struct __attribute__ ((__packed__)) {
    int numberB;
    std::string strA;
} StructA;

typedef struct __attribute__ ((__packed__)) {
    int numberB;
    std::string strB;
} StructB;

char *ExampleClass::getBuffer(void){
  char* mBuf;
  int offset = 10;
  return mBuf+offset;
 }

void ExampleClass::ExampleFunction(StructA *A){
    StructB *B = (StructB *)getBuffer();
    B->numberB = A->numberA;
    B->strB = A->strA;
    return;
    }

这里故意没有显示很多代码,但我相信我的问题的根源确实得到了证明:为什么我在尝试分配 B->strB = A->strA 时出现分段错误?

谢谢

【问题讨论】:

  • 您正在取消引用一个未初始化的指针 (B->numberB = ...)。
  • 抱歉,在实际情况下,指针已初始化,我更新了示例以显示实际如何使用它。调试时正确分配 int 字段。字符串是导致段错误的原因
  • @DanielKlisiewicz 你不能跳过string(或整个struct)的构造。
  • 感谢@appleapple。在 getBuffer 函数中,我构造了一个 (char*),然后将其转换为 (B*)。这是不允许的吗?编译器似乎没有抱怨。听起来可能很傻,但是如果我从 (char*) 转换获得整个结构,我该如何构造字符串字段?
  • 通过将 char* 强制转换为您的结构类型,您想要的在这里是不可行的。看起来您正在尝试进行(反)序列化(这是您应该搜索的关键字)。您这样做的方式可能适用于 POD 类型,但绝对不适用于 std::string 之类的类型。

标签: c++ string pointers segmentation-fault


【解决方案1】:

getBuffer() 中,mBuf未初始化,但你将offset 添加到它,所以return'ed 的指针不确定。它当然没有指向有效的StructB 对象,这就是为什么ExampleFunction() 中的后续代码在访问B 的成员时崩溃的原因。从技术上讲,这是未定义的行为,因此任何事情都可能发生,但不能保证崩溃。

但是,即使mBuf 被初始化为一个足够大的有效char[] 缓冲区以容纳StructB 对象,在此代码中仍然没有实际构造StructB 对象,因此B->numberB 和@ 987654333@ 不是有效对象。

getBuffer() 需要做更多这样的事情:

char* ExampleClass::getBuffer(){
    char* mBuf = ...; // point to some char[] buffer that is at
                      // least 10+sizeof(StructB) in size, and
                      // isn't deallocated when getBuffer exits...
    int offset = 10;
    new(mBuf+offset) StructB;
    return mBuf+offset;
}

void ExampleClass::ExampleFunction(StructA *A){
    StructB *B = (StructB *)getBuffer();
    B->numberB = A->numberA;
    B->strB = A->strA;
    B->~StructB();
}

否则,ExampleFunction() 将需要这样做:

char* ExampleClass::getBuffer(){
    char* mBuf = ...; // point to some char[] buffer that is at
                      // least 10+sizeof(StructB) in size, and
                      // isn't deallocated when getBuffer exits...
    int offset = 10;
    return mBuf+offset;
}

void ExampleClass::ExampleFunction(StructA *A){
    StructB *B = new(getBuffer()) StructB;
    B->numberB = A->numberA;
    B->strB = A->strA;
    B->~StructB();
}

【讨论】:

  • 这是一个很棒的答案。感谢您的详细和尊重。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多