Skip to main content
Topic: Segfaults on second road stop with same default name in pak64 (Read 6565 times) previous topic - next topic

Segfaults on second road stop with same default name in pak64

In the save game at http://dl.free.fr/iHGv072NS (too big to attach here), placing a road stop (either freight or bus) at any of the three road spurs (195-197, 128,2) by the iron mine top right  will cause the game to immediately segfault. Save game was created by "Simutrans Version 102 Nightly Mar12 2009" (current debian/squeezy version). Crash occurs with this save game both in the creating version and in 102.1-2457.  Pak is pak64 (plain pak that is) and I am running Debian/squeezy with Gnome.

The crux seems to be that there is already an existing road stop with the same default name as the one about to be created. Changing language so that the default name will be another prevents crash, as does manually renaming the existing road stop at (194,138-140,2).

I have not tested if other types of stops apart from road stops are affected.

This may be the same problem as reported by in http://forum.simutrans.com/index.php?topic=2181.0 and/or http://forum.simutrans.com/index.php?topic=1761.0 but I lack sufficient detail to ascertain that it is so; I have f ex seen no relation to the rotation of the map. I apologize if this in fact turns out to be a double bug report.

Log tail (-log 1; adding -debug 3 adds no further info):
Warning: route_t::find_route():   Too many steps (37>=max 1000000) in route (too long/complex)
<snip many more like this>
Warning: route_t::find_route():   Too many steps (37>=max 1000000) in route (too long/complex)
Warning: route_t::find_route():   Too many steps (37>=max 1000000) in route (too long/complex)
Message: karte_t::interactive_event(event_t &ev):   calling a tool
Message: wkz_halt_aux():   building CarStop on square 197,128 for waytype 1

strace tail:
17117 nanosleep({0, 5000000}, {0, 5000000}) = 0
17117 gettimeofday({1242372899, 913688}, NULL) = 0
17117 gettimeofday({1242372899, 913729}, NULL) = 0
17117 read(4, "\5\1\211\0\310\314\252U{\0\0\0\r\0`\3\0\0\0\0\302\1\305\0\270\1\201\0\0\1\1\0"..., 4096) = 32
17117 read(4, 0x88830f0, 4096)          = -1 EAGAIN (Resource temporarily unavailable)
17117 read(4, 0x88830f0, 4096)          = -1 EAGAIN (Resource temporarily unavailable)
17117 select(5, [4], NULL, NULL, {0, 0}) = 0 (Timeout)
17117 gettimeofday({1242372899, 914000}, NULL) = 0
17117 nanosleep({0, 5000000}, {0, 5000000}) = 0
17117 write(3, "Message: karte_t::interactive_eve"..., 65) = 65
17117 write(2, "Message: karte_t::interactive_eve"..., 50) = 50
17117 write(2, "calling a tool"..., 14) = 14
17117 write(2, "\n"..., 1)              = 1
17117 write(3, "Message: wkz_halt_aux():\tbuilding"..., 74) = 74
17117 write(2, "Message: wkz_halt_aux():\t"..., 25) = 25
17117 write(2, "building CarStop on square 197,12"..., 48) = 48
17117 write(2, "\n"..., 1)              = 1
17117 --- SIGSEGV (Segmentation fault) @ 0 (0) ---
17120 +++ killed by SIGSEGV +++

Re: Segfaults on second road stop with same default name in pak64

Reply #1
I tried it and it worked. Sometime the translations are broken. Try to download new translations from simutrans-germany.com/translator.

Re: Segfaults on second road stop with same default name in pak64

Reply #2
I am afraid that I am not totally convinced that the error lies with the translation. It is however clear that I provided too little detail in my original bug report. To provoke the crash, the default name of the new road stop must be exactly the same as the one already created, that is it only crashes with the given save game if you have the same language (Swedish) selected with the same sv.tab as the save game was created with (which is fresh from the SimuTranslator).

In order to facilitate debugging I have uploaded a slightly modified save game to http://dl.free.fr/p5fOoDfOY. In this game I have already created a road stop at one of the three spurs with the language set to German (my de.tab is the one distributed with Simutrans Version 102 Nightly Mar12 2009). It is now possible to provoke the crash by placing a new road stop at 198,129,2 (that is a fourth spur below the mine, far away enough to become a new road stop instead of extending the previous stop) with German language setting. It shows the same behaviour as previously, if there exists a road stop with the same name as the newly created, it crashes; if that previous road stop is renamed (so it diverges from the default) it does not crash; if you change language setting to another language so that the new default name will be different it does not crash. If you are not using German, or if your de.tab does not match mine, try removing the road stop at 197,127,2 then rebuilding it, followed by building another at 198,129,2.

Re: Segfaults on second road stop with same default name in pak64

Reply #3
I could build as many roadstops as I like in any language (ok, I stopped after five or so). Maybe this is a compiler problem.

Re: Segfaults on second road stop with same default name in pak64

Reply #4
Bad translations ought not cause the game to crash. The problem, I suspect, is in the frequent use of the sprintf command: if the translation does not specify the correct number and type of format specifiers, sprintf will give an access violation. Better either to avoid putting format specifiers in translation texts, or replace sprintf with something else.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Re: Segfaults on second road stop with same default name in pak64

Reply #5
Well, I still do not think translations are at fault here, I can provoke the segfault no matter what language I use - as long as there is already one roadstop by the same name as the one about to be created should be given, the game segfaults. I just tied up the one loose end I found in my testing and downloaded the latest nightly of pak64 as well, and the problem is still there.

So if you can have multiple road stops with the same name, and I can not.. well then I do not know what to do next. Please advice me on how I should proceed to provide you with the information you need.

Re: Segfaults on second road stop with same default name in pak64

Reply #6
Experience shows that Linux and Windows behave differently when it comes to access violations. So, using Linux will be necessary to check.

BTW, a little old script of mine tells me about these current problems with printf() placeholders in translations:
different placeholders in file cn.tab:
   %s\nnow operates\n%i trucks between\n%s at (%i,%i)\nand %s at (%i,%i).
     %s %i %s %i %i %s %i %i <-> %s %s %i %i %s %i %i %i
   %i km/h (max. %ikm/h)
     %i %i <-> % k %i
different placeholders in file es.tab:
   Percent Electricity
      <-> % d
different placeholders in file hr.tab:
   %s now\noffers bus services\nbetween %s\nand factory\n%s\nat (%i,%i).\n
     %s %s %s %i %i <-> %s %s %i %i
different placeholders in file zh.tab:
   P****engers %d %c, %d %c, %d no route
     %d %c %d %c %d <-> %d %d %d

Re: Segfaults on second road stop with same default name in pak64

Reply #7
I have encountered the same bug in another save game, yet again with pak64, this time with placing a railway stop. In both instances the stop was about to be placed next to a factory (iron mine in first case, oil pump in second) a bit away from the nearest city and with another factory of the exact same type in the vicinity. I have tested the first save game on windows, and it does not cause any problems there.

By adding a plethora of debug messages to the code, I have been able to pinpoint where the game segfaults on debian/squeezy.

It happens in simhalt.cc:631 :
Code: [Select]
dirname = direction_name[(0-welt->get_einstellungen()->get_rotation())%4];;

As long as it says 0-welt on this line, the game segfaults, changing it to either 1-welt, 2-welt, 3-welt or 4-welt prevents the segfault and the game seems to continue normally - the stop gets a unique name. I have however been unable to read the code clearly enough to be able to choose which of these settings is the intended, nor to see if there is any other ill effects of changing this particular variable.

As I said, the problem does not occur on windows, and I am using gcc 4.3.3.

Re: Segfaults on second road stop with same default name in pak64

Reply #8
as the result of 0-welt->.. will face a modulo 4 operation, it is at least equivalent to 4-welt... ;) maybe this bug is compiler specific?
Parsley, sage, rosemary, and maggikraut.

Re: Segfaults on second road stop with same default name in pak64

Reply #9
I would think so too. Changing to 4 is albeit an easy fix ...

However I am a little surprise how an unit8 module 4 can give an number outside 0...3. My math background told me different ....

Re: Segfaults on second road stop with same default name in pak64

Reply #10
Is the first operand a negative number, or is there an underflow (unsigned integer)? Either would be a reason for failure.

Re: Segfaults on second road stop with same default name in pak64

Reply #11
But after modulo 4 it should be between 0...3 or my definition of modulo does not match that of the compiler ...

Re: Segfaults on second road stop with same default name in pak64

Reply #12
I did some web (re-)search, and several websites list claims that the behaviour is implementation-defined (at least before C99, someone wrote), that means, i%n (with i<0) can give you a value between -n+1 and n-1, inclusive. http://www.embeddedgurus.net/stack-overflow/2009/05/signed-versus-unsigned-integers.html (search for "Modulus Operator"). Nowadays, it is more likely a compiler bug (compilers don't care about mathematics).

Conclusion: don't use C modulo operator on values <0.  :-[

 

Re: Segfaults on second road stop with same default name in pak64

Reply #13
Since no one really seemed to properly understand WHY changing 0 to 4 would make any difference I continued to mull over the matter. I added the following debug output lines to simhalt.cc:
(It might be that the %i-casting done by the DBG_MESSAGE is confusing the whole issue... in which case I apologize for taking up your time)
Code: [Select]
uint8 current_rotation = welt->get_einstellungen()->get_rotation();
DBG_MESSAGE("simhalt.cc::haltestelle_t::create_name", "Current rotation %i.", current_rotation);
current_rotation = 0-welt->get_einstellungen()->get_rotation();
DBG_MESSAGE("simhalt.cc::haltestelle_t::create_name", "0-xx: %i.", current_rotation);
current_rotation = (0-welt->get_einstellungen()->get_rotation())%4;
DBG_MESSAGE("simhalt.cc::haltestelle_t::create_name", "%4: %i.", current_rotation);
current_rotation = welt->get_einstellungen()->get_rotation();
DBG_MESSAGE("simhalt.cc::haltestelle_t::create_name", "Current rotation %i.", current_rotation);
current_rotation = 4-welt->get_einstellungen()->get_rotation();
DBG_MESSAGE("simhalt.cc::haltestelle_t::create_name", "4-xx: %i.", current_rotation);
current_rotation = (0-welt->get_einstellungen()->get_rotation())%4;
DBG_MESSAGE("simhalt.cc::haltestelle_t::create_name", "%4: %i.", current_rotation);
When placing a stop on an unrotated map this gives the following output:
Code: [Select]
Message: simhalt.cc::haltestelle_t::create_name:	Current rotation 0.
Message: simhalt.cc::haltestelle_t::create_name: 0-xx: 0.
Message: simhalt.cc::haltestelle_t::create_name: %4: 0.
Message: simhalt.cc::haltestelle_t::create_name: Current rotation 0.
Message: simhalt.cc::haltestelle_t::create_name: 4-xx: 4.
Message: simhalt.cc::haltestelle_t::create_name: %4: 0.
That is the result of 0- and 4- are identical. However, when placing the bus stop on a rotated map, I get the following output:
Code: [Select]
Message: simhalt.cc::haltestelle_t::create_name:	Current rotation 1.
Message: simhalt.cc::haltestelle_t::create_name: 0-xx: 255.
Message: simhalt.cc::haltestelle_t::create_name: %4: 255.
Message: simhalt.cc::haltestelle_t::create_name: Current rotation 1.
Message: simhalt.cc::haltestelle_t::create_name: 4-xx: 3.
Message: simhalt.cc::haltestelle_t::create_name: %4: 3.
That is, with a 4 I get the expected '3' from modulo, but with 0 it does not work.

Just for comparison, I then tested with declaring current_rotation as a plain int, and with an explicitly set sint8, instead, and then (for both at least - getting very suspicious of the int-types right now!) I get the following output on a rotated map:
Code: [Select]
Message: simhalt.cc::haltestelle_t::create_name:	Current rotation 1.
Message: simhalt.cc::haltestelle_t::create_name: 0-xx: -1.
Message: simhalt.cc::haltestelle_t::create_name: %4: -1.
Message: simhalt.cc::haltestelle_t::create_name: Current rotation 1.
Message: simhalt.cc::haltestelle_t::create_name: 4-xx: 3.
Message: simhalt.cc::haltestelle_t::create_name: %4: 3.
That is again modulo is broken with 0-

So finally I got a "bit" exasperated and decided to do a "force test". I added the following debug output:
Code: [Select]
uint8 forcetest_u = 0;
forcetest_u = forcetest_u - 1;
sint8 forcetest_s = forcetest_u;
DBG_MESSAGE("simhalt.cc::haltestelle_t::create_name", "Force test: u =  %i / %i ; s = %i / %i", forcetest_u, forcetest_u%4, forcetest_s, forcetest_s%4);
which yielded the following output:
Code: [Select]
Message: simhalt.cc::haltestelle_t::create_name:	Force test: u =  255 / 3 ; s = -1 / -1
which I interpret (and this might very well be totally wrong) as that modulo on a uint8 works fine, but if it is cast to a signed integer, whether explicitly by sint8 or implicitly by being subtracted from a plain numeral (0-...), will result in modulo on a negative number, which in turn fails.

Quote from: prissi
However I am a little surprise how an unit8 module 4 can give an number outside 0...3. My math background told me different ....
The thing is... that as far as I can tell from the above, it is no longer a uint8 when the modulo is applied.

I am sorry for such a long and hard to read post.
--
Stats: debian/squeeze, gcc 4.3.3, Source: modified svn up from 2009-06-04, compiled with debug 3 (compiled once with optimisations and then a clean build without them, both show same behaviour)


EDIT: The conclusion of this test, which I forgot to include *blush*, is that the modification of 0- to 4- is insufficient, since the same error may  occur with 1-, 2- as well (if the rotation is larger than the numeral). Perhaps a explicit cast such as
Code: [Select]
dirname = diagonal_name[((uint8) 0-welt->get_einstellungen()->get_rotation())%4];
could be used, but I have no idea how that would impact performance.

Re: Segfaults on second road stop with same default name in pak64

Reply #14
The problem seems to be with the subtraction: "0-xx: 255" is already an underflow, and it happens because the compiler does not expand the uint8 operand (compiler bug?) => an explicit cast to at least sint16 is needed. EDIT: after that, there is still the "implementation-defined" problem with modulus operator, that I described above. Can the rotation indicator become larger than 3?

Oh, and printf("%i") will also not expect a uint8 (it should be one byte, right?) on the stack.

Re: Segfaults on second road stop with same default name in pak64

Reply #15
EDIT: after that, there is still the "implementation-defined" problem with modulus operator, that I described above. Can the rotation indicator become larger than 3?

AFAICT it cannot, so maybe the simple solution of changing 0 to 4 should perhaps be expanded to adding 4 to the rest of the array index calculations as well, i.e., 1 -.... to 5-... etc, to avoid the problem of underflow/modulo with negative numbers without(?) introducing any problems elsewhere?

Re: Segfaults on second road stop with same default name in pak64

Reply #16
I changed the problematic part in rev 2506. Thank you for reporting and insisting on the issue :)
Parsley, sage, rosemary, and maggikraut.