Home > Software design >  Why do I get a seg fault when assigning a string pointer to a string pointer?
Why do I get a seg fault when assigning a string pointer to a string pointer?

Time:10-01

Consider the following simplified code:

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;
    }

There is a lot of code not shown here intentionally, but I believe the root of my question do be demonstrated: Why do I get a segmentation fault when trying to assign B->strB = A->strA?

Thanks

CodePudding user response:

In getBuffer(), mBuf is uninitialized, but you add offset to it, so the pointer being return'ed is indeterminate. It certainly does not point at a valid StructB object, which is why the subsequent code in ExampleFunction() crashes when accessing B's members. Technically, this is undefined behavior, so anything can happen, a crash is not guaranteed.

But, even if mBuf were initialized to a valid char[] buffer large enough to hold a StructB object, there is still no StructB object actually being constructed in this code, thus B->numberB and B->strA are not valid objects.

getBuffer() would need to do something more like this:

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();
}

Or else, ExampleFunction() would need to do this instead:

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();
}
  • Related