0

I'm trying to run an old MUD driver compiled with added -g flag and removed -O2 flag, so that I can debug it. I have a function with a prototype void try_to_swap(void), but the definition is void try_to_swap(volatile int* interrupted). Inside the function the value of that pointer is checked:

if(*interrupted)
    ...

The function is called without parameters, like the prototype - try_to_swap();

Everything works OK with the optimization flag. But without it I get a SIGSEGV when the function is called. The problem is that the pointer points to an address which is unreachable for the process (0x3b - every time), thus the segmentation fault.

My question is:

a) Why don't I get any errors during make? Shouldn't the lack of the parameter in the call be somehow noticed by the compiler?

b) During optimization, does the compiler somehow take care of the value of the pointer so the program won't crash?

c) What would be the right way to tackle this? Remove the pointer from definiton, add it to the prototype? The pointer is used only in this function, and only in mentioned if. It doesn't seem to be initialized anywhere. Or maybe it's somehow automatically initialized? I'm not too familiar with volatile pointers. But the pointer value is random garbage from the stack set before the function call, as no parameter value was provided. Is this even legal in C, where default values are not an option?

Bart
  • 420
  • 3
  • 18
  • 5
    When the function tries to use the arguments that you don't pass then you have *undefined behavior*. Don't do it! – Some programmer dude Aug 09 '15 at 12:39
  • 3
    If you *must* call the function without arguments, then make *two* functions, one taking arguments, and another that takes no arguments and call the other functions with some default arguments. – Some programmer dude Aug 09 '15 at 12:40
  • Why it it was decided it's called without arguments is a mystery to me. Maybe in some previous versions a volatile int was used to determine some kind of interrupt signal. But the function is declared with `void` as parameter. So why doesn't the linker complain when the definition doesn't match the prototype? – Bart Aug 09 '15 at 12:45
  • 3
    In C the function call is only checked against the declared prototype at compilation time, no checks are possible at link time. Only C++ have the arguments as part of the function signature, not C. – Some programmer dude Aug 09 '15 at 12:53
  • Thanks to your comments I found the information [here](http://stackoverflow.com/questions/2575153/must-declare-function-prototype-in-c), but I was still puzzled with the linking. Now it makes sense, C doesn't have mangling so only the name is checked. Thanks very much for your answer! – Bart Aug 09 '15 at 12:58
  • Somebody decided to be a bit too clever and rely on undefined behaviour without documenting it. Now you need to reverse engineer their line of thought and understand what that mystery parameter means and where it comes from and why and when it becomes zero or non-zero. This means debugging at the assembly level, with optimisations on. Sorry about that. It is probably important to keep the optimisation on for the callers of that function. not for the function itself. – n. m. could be an AI Aug 09 '15 at 12:59

1 Answers1

1

a) In C, () means "any arguments" and isn't the same as (void) which is no argument. try_to_swap() is valid but not a good documentation for users.

b) Yes, the compiler seems to detect the missing parameter and just passes a null pointer.

c) You could add the pointer argument to the prototype and pass what's required by the internal if or try a trick.

Youka
  • 2,646
  • 21
  • 33