0

I am working on a code with an user interface in C and I have a problem with char pointers. Another person of my team made an algoritm with something like this:

typedef struct
   int index;
   char * buffer;
   //...another fields
} ui_cfg;

int ui_Function (ui_cfg *cfg)
{
   char localBuffer[100];
   cfg->buffer = localBuffer;

   printf("\n[1]cfg->buffer %p", cfg->buffer);
   printf("\n[2]localBuffer %p", localBuffer);

   Adapter(cfg->buffer);
   printf("\n[3]localBuffer %p", localBuffer);
   printf("\n[4]cfg->buffer %p", cfg->buffer);

   //...irrelevant code
}

This is a very, very simplificated version of the code, but it has the essential parts. In the real code, Adapter is called with a function pointer in a secundary function. Adapter function does a thing like this:

int Adapter (char * buffer)
{
   int idx;
   idx = sprintf (buffer, "Test string");

   return idx;
}

My problem is the next one. When I run the code, it throws Segmentation Fault in the printf("\n[4]cfg->buffer %p", cfg->buffer); instruction. However, the other printf works fine and shows the same memory direction. I don't understand why the code crashes at this point. What could be the problem?

Details: This code compiles with arm-brcm-linux-gnueabi-gcc and mipsel-linux-uclibc-gcc on two different architectures. On ARM, this codes works fine and cfg-buffer contains "Test string". On MIPSEL, the code throw segmentation fault.

JCMiguel
  • 155
  • 1
  • 2
  • 11
  • 1
    @πάνταῥεῖ not in the provided code sample, though - there is no out-of-scope access there. – SergeyA Jul 19 '18 at 19:06
  • I'm am wondering, in the real code, are you also writing `idx = sprintf (buffer, "Test string");` or is the string written much longer? – hetepeperfan Jul 19 '18 at 19:07
  • @SergeyA Well, _`cfg->buffer = localBuffer;`_ implies that `cfg->buffer` might be accessed at other parts of the code, no? – πάντα ῥεῖ Jul 19 '18 at 19:08
  • @hetepeperfan, the string is longer but smaller than 100 characters. Tipically, it has round 40 characters with NULL. – JCMiguel Jul 19 '18 at 19:13
  • @πάνταῥεῖ there is a strong indication it might, but current sample doesn't show it. I am leaning to VTC as lacking MCVE. – SergeyA Jul 19 '18 at 19:15
  • Could you work this code into a MCVE so people with the same architecture can attempt to reproduce it? – Davislor Jul 19 '18 at 19:36
  • Note that debugging error messages should **end** with a newline; they often don't need to start with a newline. You might be being misled about where the crash occurs because some other debugging message is printed, and its starting newline flushes the `printf()` that you think is causing the trouble, but the trouble occurs after the next debugging output (but you don't see that because the next message was not flushed because it didn't end with a newline). Calling `fflush(stdout)` or `fflush(0)` after each `printf()` is another option. – Jonathan Leffler Jul 19 '18 at 23:53

1 Answers1

2

Change your ui function like this:

// caller will need to free cfg->buffer when finished using
int ui_Function (ui_cfg *cfg)
{
   char* heapBuffer = malloc(100);
   cfg->buffer = localBuffer;
   // etc
}

Or alternatively:

int ui_Function (ui_cfg *cfg, char* buffer)
{
  cfg->buffer = buffer;
  // etc
}

With your current version, localBuffer is a stack variable and is cleaned up when the function returns. On some operating systems it may be accessible still after the function returns (possibly for some short period) but on other will get re-used for some other use. It is what is called undefined behaviour and is BAAAAAD.

To allocate some memory which will still exist when the function returns you can either allocate some memory from the heap or pass in your own buffer to the function.

Don't forget to free up any heap memory used when you are finished with the cfg.

Angus Comber
  • 9,316
  • 14
  • 59
  • 107
  • You're right, but I have the same problem using malloc(). I don't know the reason. I tested with a `int Adapter (char ** buffer)` function. I implemented `Adapter(&cfg->buffer);` and the code also throw fault. – JCMiguel Jul 20 '18 at 13:53
  • @JCMiguel Then your Adapter function must be corrupting the cfg struct or something like that. Show the Adapter function. – Angus Comber Jul 21 '18 at 16:58
  • I was able to solve my problem. There was a char array of five elements and I wrote a string too long in it, and then I copied the array's content in the cfg->buffer with `sprinf(...)`. I think the code throw the fault because the content of the local variable is inaccessible after exit. However, I don't undestand the whole reason why I can't access with cfg->buffer. Should I edit my question with the complete function? – JCMiguel Jul 23 '18 at 12:46