News:

Use the "Forum Search"
It may help you to find anything in the forum ;).

Query about welt->lookup()

Started by jamespetts, September 15, 2013, 01:27:16 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

jamespetts

I find that this method seems to fail on occasions, and it is not entirely clear to me why. Running welt->lookup(pos) inside simfab.cc (where "pos" is therefore the "pos" value stored by a factory), occasionally, the method returns a NULL pointer. The factories in question are on solid ground, and is not a fishery ("fish swarm").

If I run welt->lookup_kartenboden(pos.get_2d()), then I get a valid gr pointer - but if I then run gb = gr->find<gebaeude_t>(); on the gr pointer, I get a NULL pointer for gb in the cases where welt->lookup(pos) returned a NULL, whereas gb always returns a pointer to the gebeaude_t object on the tile occupied by the factory's premier position in all other cases.

I am a little perplexed by this, and should appreciate any assistance.
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.

Dwachs

Then pos is not valid, maybe there is a hole in the factory and not all tiles are occupied ?
Parsley, sage, rosemary, and maggikraut.

jamespetts

#2
Hmm, no, the factory is the Pak128.Britain coal fired power station, which has no holes, and the pos is right in the middle of it. The factory is near a slope, but the tile to which "pos" refers is at least a tile away from the slope edge so far as I can make out.

Edit: Even more perplexingly, if I try to cirvumvent the problem by storing and using a pointer to the relevant gebaeude_t object in the fabrik_t class, using the pointer to the gebaeude_t object returned by this line:


gebaeude_t* gb = hausbauer_t::baue(welt, besitzer_p, pos_origin, rotate, besch->get_haus(), this);


I get all sorts of weird memory corruption errors that I am at a loss to understand, some suggesting that those pointers somehow become invalid, but some other, even weirder issues, including an index out of bounds error in this part of code whenever I try to load a saved game after demo.sve has loaded:

// restore city pointer here
    if(  file->get_version()>=99014  ) {
        sint32 city_index = -1;
        if(  file->is_saving()  &&  ptr.stadt!=NULL  ) {
            city_index = welt->get_staedte().index_of( ptr.stadt );
        }
        file->rdwr_long(city_index);
        if(  file->is_loading()  &&  city_index!=-1  &&  (tile==NULL  ||  tile->get_besch()==NULL  ||  tile->get_besch()->is_connected_with_town())  ) {
            ptr.stadt = welt->get_staedte()[city_index];
        }
    }


Any assistance as to why this might be, and whether the two problems are related, would be much appreciated.
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.

Philip

I'm seeing this during factory creation/destruction, when presumably it isn't a big issue. Are you seeing it during normal operation, too?

jamespetts

Yes, unfortunately - if one were to load demo.sve and run it for a while, without the check for "!gb" in the line:

const sint64 base_pax_demand = (!gb || gb->get_tile()->get_besch()->get_employment_capacity() == 65535) ? (besch->get_pax_demand() == 65535 ? besch->get_pax_level() : besch->get_pax_demand()) : gb->get_jobs();

(and its equivalent for mail), the game would quickly crash here, as "gb" will end up as a NULL pointer with some specific factories (which are the same each time).
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.

Philip

Hmm. When I try that, I see the NULL pointer, but only when a new factory is being built:

#0  fabrik_t::update_scaled_pax_demand (this=0x15f955f0) at simfab.cc:352
#1  0x0828505b in fabrik_t::fabrik_t (this=0x15f955f0, pos_=..., spieler=0x15b21a38, fabesch=0x1517c2f8,
    initial_prod_base=-1) at simfab.cc:851
#2  0x08053341 in fabrikbauer_t::baue_fabrik (welt=0x88eeea0, parent=0x0, info=0x1517c2f8, initial_prod_base=-1,
    rotate=1, pos=..., spieler=0x15b21a38) at bauer/fabrikbauer.cc:402
#3  0x08053e6d in fabrikbauer_t::baue_hierarchie (parent=0x0, info=0x1517c2f8, initial_prod_base=-1, rotate=1,
    pos=0xffffb2fa, sp=0x15b21a38, number_of_chains=1) at bauer/fabrikbauer.cc:629
#4  0x08056810 in fabrikbauer_t::increase_industry_density (welt=0x88eeea0, tell_me=true,
    do_not_add_beyond_target_density=true, power_stations_only=true) at bauer/fabrikbauer.cc:1117
#5  0x083037d5 in karte_t::new_month (this=0x88eeea0) at simworld.cc:3817
#6  0x08304d7c in karte_t::step (this=0x88eeea0) at simworld.cc:4161
#7  0x08314b78 in karte_t::interactive (this=0x88eeea0, quit_month=2147483647) at simworld.cc:8423
#8  0x082bc6bf in simu_main (argc=1, argv=0xffffd7b4) at simmain.cc:1259
#9  0x082ca350 in sysmain (argc=1, argv=0xffffd7b4) at simsys.cc:703
#10 0x08361d42 in main (argc=1, argv=0xffffd7b4) at simsys_s.cc:723

I think the issue here is that the ground hasn't been raised or lowered to build the actual factory yet, so there is no grund at the given (3d) position:

(gdb) p welt->lookup(pos)
$1 = (grund_t *) 0x0
(gdb) p pos.z
$2 = 1 '\001'
(gdb) p pos.z = 2
$3 = 2 '\002'
(gdb) p welt->lookup(pos)
$4 = (grund_t *) 0x0
(gdb) p pos.z = 0
$5 = 0 '\000'
(gdb) p welt->lookup(pos)
$6 = (grund_t *) 0x1561d274

Now the issue is whether it's okay not to update those values before building the factory. I think it is, and that we should move the calls to update_scaled_{electric,pax,mail}_demand to baue() from the fabrik_t constructor, which is called before the factory actually makes it onto the map.

jamespetts

I think that I have discovered what the problems were with the storing of pointers: one was an unrelated problem concerning the use of the IGNORE_ZERO_WEIGHT preprocessor definition which caused trouble when loading certain cities; the other was caused by calling certain code unnecessarily when factories are deleted when the map is being deleted. Both are now fixed on the passenger-generation branch.

This method of storing the pointer to the building in the fabrik_t object is probably preferable in any event, and should deal with the issues relating to NULL pointers being unexpectedly returned, although it is still not clear to me why this is so in factories that have already been built (although the explanation as to why this occurs with newly built factories is useful - thank you).
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.