If it’s the kind of thing I’m thinking about, the reason is "reference emulation". As you may know, functions in C pass their parameters by value/copy. To emulate the reference pass, you need to pass the pointers to the desired parameters and work with these pointers.
A half-haired example to fix:
void badswap (int a, int b){
int tmp;
tmp = a;
a = b;
b = tmp;
}
void goodswap (int *ap, int *bp){
int tmp;
tmp = *ap;
*ap = *bp;
*bp = tmp;
}
To add an element to the end of a chained list, you pass the head of the list as parameter, because that head will not be modified. You will only modify the tail by adding an element at the end of it.
Already in the second, to add an element to the head of the list, effectively you have to modify the head of that list: it was previously in the memory location X, now it will be in the memory location Y. For so, you will have to use the reference emulation.
I think to explain the cause of the mistake, I would have to do a table test, "interpreting mentally" the code itself. My best guess, for now, is that there should be some confusion of variables - imagine as if you wrote something like *tmp = *bp;
in the code of goodswap
. But again, to point out for sure, I would have to see the full code. These Segmentation fault errors are difficult to explain in a "generic way".
Tip: if possible, read us warnings compiler. They may contain useful insights about these errors. There are also other software, such as cppcheck, the splint or even the debugger gdb.
EDIT:
I got home and tested the modified code in Clang. Well, as I imagined, the error is precisely in the parameter passage.
First of all, the way you did these two functions is different from what I had thought, but it’s even cleaner and more functional. In this sense, much of my comment on reference emulation is unnecessary.
Secondly, to cut to the chase, here’s Clang’s message:
testno.c:66:22: warning: incompatible pointer types passing 'tipo_lista **' (aka 'struct tipo_lista **') to parameter of type
'tipo_lista *' (aka 'struct tipo_lista *'); remove & [-Wincompatible-pointer-types]
p = inserir_inicio(&p,cria_no(2));
^~
testno.c:37:43: note: passing argument to parameter 'p' here
tipo_lista * inserir_inicio (tipo_lista * p, tipo_lista * novo_no)
^
1 warning generated.
With this, the function waits for a pointer, but you are passing a pointer-to-the-pointer. It is not surprising that you will have an erratic behavior - if I am not mistaken, in fact this would be a case of undefined behavior: the compiler is free to do as he pleases. By "well understood", I mean "anything from firing nuclear missiles if there’s hardware for it to melt the monitor".
BUT, assuming the compiler translates this as "obvious" as possible, he simply treats &p
as if it were a memory position. "The programmer knows what he is doing". Since this memory position was not legally allocated, it can be anywhere, most likely in a segment that does not belong to the program. And you’ll get a beautiful SIGSEGV
.
I hope I’ve helped!
Post Scriptum: I left out some nauseous tests in my example on IDEONE; for example, if the memory was really allocated. Still, you can spend...
For a precise answer, we need the function code
inserir_inicio
andinserir_fim
. Although we are almost sure of the problem, without it it is difficult to give a really good answer.– Wilker
@Wilker already added in the question the functions I did.
– André
In accordance with the definition of those tasks,
inserir_inicio(&p, cria_no(0))
andp = inserir_fim(p, cria_no(0))
cannot both be certain if they refer to the same variablep
. Posta also themain()
, please– Wtrmute
Posted, note that is commented.
– André