LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Slackware (https://www.linuxquestions.org/questions/slackware-14/)
-   -   GCC update to another version (https://www.linuxquestions.org/questions/slackware-14/gcc-update-to-another-version-4175733291/)

selfprogrammed 01-31-2024 04:17 PM

Would be interesting if anyone else was able to compile Voxelands, and run it for more than 12 hours without getting one of these segfaults (it takes a while). It is addictive.

I tried Valgrind (I think it was this program). It tried for about 10 minutes then came back that the program was doing something that it does not support, then it gave up. All the exceptions alone might have thrown it off.

I have looked at CMAKE docs about how to specify your choice of compiler. Any CMAKE supported way to specify that, so far eludes me. Trying to do this within a Slackbuild script that wants to rebuild EVERYTHING does not help. I have modified that slackbuild script into a build debug version that can get around that problem.

Amazing that this thing will compile without warnings. It saves its weirdness for run-time.
I did notice that it specifies the optimization, and then respecifies differently for debugging. I wonder if the debugging and optimization combination is adding to the confusion.
That would be another CMAKE issue that probably is difficult to override.

That this many programmers cannot see what the problem with this, and can come up so many possibilities, indicates that it is mostly a C++ language problem. Trying CLANG just to avoid the issue is not a real solution, but it might give indications as CLANG has it own error detection.

The solution is to avoid the questionable constructor practices, and put in ones that are safe and sure. The compiler can be trusted to see the duplicated effort and optimize it out. Do not really need the programmer playing tricks just to avoid assigning to a field after it was default initialized.
As I already have put this much effort into it, this should get fixed (instead of just using CLANG, even if it worked better).

I was wondering about the fix where putting a test for an empty vector, before using an iterator on it. I would think that those std:: operators were more robust than that. Anyone sure about whether iterators need protection against empty vector lists ?

I would still like to have an upgrade on GCC though. Getting GCC up to 11.4 may be a small step, but it avoids whatever they did that required jumping to 12.0.
If I have to do this myself, I am likely going to have to replace the slack package entirely. My code is not having these problems because I avoid these kind of iffy constructs.
Having a alternative version in /opt will not help if I cannot use it in place of the installed GCC with these problem slackbuilds. I really need some way to switch out the compiler that the whole slackbuild sees.

rkelsen 01-31-2024 11:18 PM

Quote:

Originally Posted by selfprogrammed (Post 6480182)
I will eventually submit patches to the actual maintainers of this program. From past experience, it is not likely the maintainer will accept them.

You're probably right about that:
Quote:

25 Jul 2018 at 7:09pm
"I've decided to just let Voxelands die, it was fun while it lasted, but it's just become a chore lately.

I'm still working on other games, one of which 'The Void' will be available on itch.io soonish."

https://forum.minetest.net/viewtopic.php?t=20448

The last update to the project was in May 2018.

BrunoLafleur 02-01-2024 01:20 AM

Quote:

I tried Valgrind (I think it was this program). It tried for about 10 minutes then came back that the program was doing something that it does not support, then it gave up. All the exceptions alone might have thrown it off.
Valgrind is very time consuming. It can be a hundred times the normal execution time. But it can give very good information at the very beginning of a memory problem. Else with gdb the bugs maybe visible soon enough to be trapped an it is quicker.

BrunoLafleur 02-01-2024 01:27 AM

For cmake something like :

cmake -DCMAKE_C_COMPILER=... -DCMAKE_CXX_COMPILER=...
added aside the usuals -DCMAKE_CXX_FLAGS and -DCMAKE_C_FLAGS

pan64 02-01-2024 01:29 AM

Quote:

Originally Posted by selfprogrammed (Post 6480545)
I have looked at CMAKE docs about how to specify your choice of compiler. Any CMAKE supported way to specify that, so far eludes me. Trying to do this within a Slackbuild script that wants to rebuild EVERYTHING does not help. I have modified that slackbuild script into a build debug version that can get around that problem.

I don't know what it is, but again there should be a variable CC to specify the compiler. It should work on all cmake and make based builds.

Quote:

Originally Posted by selfprogrammed (Post 6480545)
Amazing that this thing will compile without warnings. It saves its weirdness for run-time.
I did notice that it specifies the optimization, and then respecifies differently for debugging. I wonder if the debugging and optimization combination is adding to the confusion.

those are mainly incompatible with each other. Optimization may (and will) change the code, so the result cannot be connected to the source lines. You can use still a low level debugger on the running code, if you wish, but you will not be able to follow the source code. It does not depend on the tool you use, but the level of optimization.
Quote:

Originally Posted by selfprogrammed (Post 6480545)
That would be another CMAKE issue that probably is difficult to override.

That this many programmers cannot see what the problem with this, and can come up so many possibilities, indicates that it is mostly a C++ language problem. Trying CLANG just to avoid the issue is not a real solution, but it might give indications as CLANG has it own error detection.

The solution is to avoid the questionable constructor practices, and put in ones that are safe and sure. The compiler can be trusted to see the duplicated effort and optimize it out. Do not really need the programmer playing tricks just to avoid assigning to a field after it was default initialized.
As I already have put this much effort into it, this should get fixed (instead of just using CLANG, even if it worked better).

I was wondering about the fix where putting a test for an empty vector, before using an iterator on it. I would think that those std:: operators were more robust than that. Anyone sure about whether iterators need protection against empty vector lists ?

I would still like to have an upgrade on GCC though. Getting GCC up to 11.4 may be a small step, but it avoids whatever they did that required jumping to 12.0.
If I have to do this myself, I am likely going to have to replace the slack package entirely. My code is not having these problems because I avoid these kind of iffy constructs.
Having a alternative version in /opt will not help if I cannot use it in place of the installed GCC with these problem slackbuilds. I really need some way to switch out the compiler that the whole slackbuild sees.

What you can do is to use different tools to identify problems, including more compilers (like clang), and using other static code analyses, like cppcheck. Also you need to check all the reported warnings. (like implicit type cast, type mismatch and other similar issues).

ponce 02-01-2024 05:54 AM

Quote:

Originally Posted by selfprogrammed (Post 6480182)
Do you have an easy and simple way to convince slackbuild and CMAKE to accept another version of GCC compiler (or clang), without having to rewrite and/or debug that effort too.
I expect it is just another option to pass to CMAKE, but I have not used such before. I have tried to configure CMAKE before, and it did not go well. I expect I will have to dive into the CMAKE docs again.
If I try to change the Makefile, CMAKE will just recreate it. The slackbuilds erasing and recreating everything does not help much either.
The chance is that I will just add to my workload. From my previous work, it might do the same exact thing, as clang does mostly what GCC does.

usually just exporting two environment variables is enough (before any configure/cmake/whatever invocation): when I want to force clang, for example, I export these
Code:

export CC=clang
export CXX=clang++

but if compilers are forced somewhere else as a parameter (like the examples Bruno has done above) that might override what specified in the environment...

selfprogrammed 02-01-2024 10:06 PM

Thank you Bruno, that may be the secret incantation that I was looking for. I wonder where you found that. I must not be getting far enough into the CMAKE docs.

I am familiar with the CC, and CXX, but I was afraid that CMAKE might just ignore or override them. CMAKE might honor environment variables, I don't know. You did not say if that worked in general or specifically did work with CMAKE. I will give up on them and will keep an eye out for those in the CMAKE docs. I do not think that I am done with those CMAKE docs.

Thank you all for your comments. I will make what use of them that I can.
This may not be immediate, as I have two other major Linux projects to work on, and they may actually produce income so I really should get some work done on them.

Voxelands: that project has been abandoned, and resurrected more times than I can keep track. That it has such a high burnout rate is not surprising considering what their code look like. I have the itch for wholesale renaming of functions at minimum, and a few other re-arrangements.
These are the more reachable bugs.

It runs threads, that seem to do something that may be database management. What is it doing with this separate MeshMake structure. This of course is perfect for out-of-sync updates and accesses causing spontaneous mystery bugs.

My last fix was putting a try/catch around a particular call to a particular getBlock call. That stopped that. It ran better for a while (several hours), then started throwing the same exception from the handler for point and click on an block, but this time because of an unguarded getNode call.
Why it repeatedly cannot find specific blocks is still a mystery (the exact same block repeatedly, but different for each run). How it treats blocks it cannot find (are they AIR, should they be automatically created?) is not documented, and I have not found anything systemic in the code that would give me a clue.

pan64 02-02-2024 12:52 AM

Quote:

Originally Posted by selfprogrammed (Post 6480781)
Thank you Bruno, that may be the secret incantation that I was looking for. I wonder where you found that. I must not be getting far enough into the CMAKE docs.

https://stackoverflow.com/questions/...g-assimp-for-i
Here is a page about that super secret, but anyway, it is pretty well documented. Here is the official: https://cmake.org/cmake/help/latest/..._COMPILER.html

BrunoLafleur 02-02-2024 03:08 AM

Quote:

Originally Posted by selfprogrammed (Post 6480781)
Thank you Bruno, that may be the secret incantation that I was looking for. I wonder where you found that. I must not be getting far enough into the CMAKE docs.

I am familiar with the CC, and CXX, but I was afraid that CMAKE might just ignore or override them. CMAKE might honor environment variables, I don't know. You did not say if that worked in general or specifically did work with CMAKE. I will give up on them and will keep an eye out for those in the CMAKE docs. I do not think that I am done with those CMAKE docs.

Thank you all for your comments. I will make what use of them that I can.
This may not be immediate, as I have two other major Linux projects to work on, and they may actually produce income so I really should get some work done on them.

Voxelands: that project has been abandoned, and resurrected more times than I can keep track. That it has such a high burnout rate is not surprising considering what their code look like. I have the itch for wholesale renaming of functions at minimum, and a few other re-arrangements.
These are the more reachable bugs.

It runs threads, that seem to do something that may be database management. What is it doing with this separate MeshMake structure. This of course is perfect for out-of-sync updates and accesses causing spontaneous mystery bugs.

My last fix was putting a try/catch around a particular call to a particular getBlock call. That stopped that. It ran better for a while (several hours), then started throwing the same exception from the handler for point and click on an block, but this time because of an unguarded getNode call.
Why it repeatedly cannot find specific blocks is still a mystery (the exact same block repeatedly, but different for each run). How it treats blocks it cannot find (are they AIR, should they be automatically created?) is not documented, and I have not found anything systemic in the code that would give me a clue.

What version of voxelands do you use ? Are your changes somewhere ? Maybe I could try to play with it and see if I can find some bugs ? If I find some time. I see there is a sbo package for voxelands. Is it uptodate with the version you use ?

selfprogrammed 02-05-2024 12:32 AM

I tried to use clang.
I used the CMAKE options specified by BRUNO.
It compiled, and I got some additional warning messages, about several things not directly relevant.
The package that was made would not run. Something is missing. The package is too small. That is all I know at this time.

If you want to join in the fun, here is my current work snapshot.
Most every debugging is in DEBUG #ifdef.

Voxelands 1709, as downloaded at slackbuilds.

The link or URL you must send to the recipient(s) of your file(s) is:
http://www.fileconvoy.com/dfl.php?id...66473d16e58211

The file(s) that can be retrieved with the above link is (are):

voxelands-v1709_debug_01.diff.tar.bz2 (24.323 KB)

The file(s) will be available on the server for the next 10 days.

In some strange way I am making it more stable, at least. It will run for a hour, and then crash several times in the next 20 minutes. It must have something to do with what actions are being done.
Most of the crashes now are failing to destroy a vector owned by one of the Mesh structures. It often starts with the QueuedMeshUpdate destructor.
Have not been able to catch what it is that is corrupted.

C++ fights me in every way with checking ptrs for validity. It will not let me do any void* comparisons, like setting a valid range for the heap and checking if the ptr in in that range.

pan64 02-05-2024 12:52 AM

Quote:

Originally Posted by selfprogrammed (Post 6481429)

C++ fights me in every way with checking ptrs for validity. It will not let me do any void* comparisons, like setting a valid range for the heap and checking if the ptr in in that range.

I just don't understand it. Probably you can show an example.
There are several different ways to check pointers, but in general a pointer can point to anywhere and can be anything on that location. Especially if the memory is overwritten for any reason.

drumz 02-05-2024 07:45 AM

Quote:

Originally Posted by selfprogrammed (Post 6481429)
C++ fights me in every way with checking ptrs for validity. It will not let me do any void* comparisons, like setting a valid range for the heap and checking if the ptr in in that range.

I think if you're trying to do tricks like this, you need an older compiler.

selfprogrammed 02-07-2024 08:15 PM

To check ptr for validity you have to check that it is within some bounds.
I tried to get a valid bounds by getting the ADDR of an early item allocated off the stack, and the MAX of other items allocated off the stack as the other limit.
The code is in the tar file that I provided 2 posts up.

The C++ compiler would not let me cast them to void, nor would it let me compare them to any ptr in that structure.
Please note that radically changing the compiler compile settings would disrupt the entire program that I am trying to debug.

It is not even a trick. It is just trying to treat a ptr to something allocated as a ptr to a memory area. How does Malloc and new get away with doing this.
Does the compiler give Malloc some special rules.

Yes, this new compiler is a problem, see original post.

I was hoping to see if Bruno got the same results I did, or if his machine behaves significantly different.

selfprogrammed 02-07-2024 11:15 PM

Got another seqfault, in a place this time where I could examine variables.
I get about 5 to 8 segfaults per 2 hour session, usually grouped together.
I work on this computer all day long, and do not see this behavior with other programs.
This is the first time I have seen this one.

InventoryList inventory.cpp:1453 segfault
Code:

(gdb) l inventory.cpp:1453

const s32 Inventory::getListIndex(const std::string &name) const
1451    {
1452            for (u32 i=0; i<m_lists.size(); i++) {
1453                    if (m_lists[i]->getName() == name)
1454                            return i;
1455            }
1456            return -1;
1457    }

(gdb) p m_lists
$3 = {data = 0x0, allocated = 0, used = 60, allocator = {_vptr.irrAllocator = 0xc0373e0},
  strategy = (irr::core::ALLOC_STRATEGY_DOUBLE | unknown: 0xc), free_when_destroyed = false,
  is_sorted = false}

(gdb) p m_lists.size()
$4 = 60

Code:

// Declaration
class InventoryList
{
public:
        InventoryList(std::string name, u32 size);
        ~InventoryList();
        void clearItems();
        void serialize(std::ostream &os) const;
        void deSerialize(std::istream &is);

        InventoryList(const InventoryList &other);
        InventoryList & operator = (const InventoryList &other);

        const std::string &getName() const;
        u32 getSize();
        // Count used slots
        u32 getUsedSlots();
        u32 getFreeSlots();

        // set specific nodes only allowed in inventory
        void addAllowed(content_t c) {m_allowed[c] = true;}
        void clearAllowed() {m_allowed.clear();}

        // set specific nodes not allowed in inventory
        void addDenied(content_t c) {m_denied[c] = true;}
        void clearDenied() {m_denied.clear();}

        // whether an item is allowed in inventory
        bool isAllowed(content_t c)
        {
                if (m_allowed.size() > 0)
                        return m_allowed[c];
                return !m_denied[c];
        }
        bool isAllowed(InventoryItem *item) {return isAllowed(item->getContent());}

        // set whether items can be stacked (more than one per slot)
        void setStackable(bool s=true) {m_stackable = s;}
        bool getStackable() {return m_stackable;}

        /*bool getDirty(){ return m_dirty; }
        void setDirty(bool dirty=true){ m_dirty = dirty; }*/

        // Get pointer to item
        const InventoryItem * getItem(u32 i) const;
        InventoryItem * getItem(u32 i);
        // Returns old item (or NULL). Parameter can be NULL.
        InventoryItem * changeItem(u32 i, InventoryItem *newitem);
        // Delete item
        void deleteItem(u32 i);

        // Adds an item to a suitable place. Returns leftover item.
        // If all went into the list, returns NULL.
        InventoryItem * addItem(InventoryItem *newitem);

        // If possible, adds item to given slot.
        // If cannot be added at all, returns the item back.
        // If can be added partly, decremented item is returned back.
        // If can be added fully, NULL is returned.
        InventoryItem * addItem(u32 i, InventoryItem *newitem);

        // Updates item type/count/wear
        void updateItem(u32 i, content_t type, u16 wear_count, u16 data);

        // Checks whether the item could be added to the given slot
        bool itemFits(const u32 i, const InventoryItem *newitem);

        // Checks whether there is room for a given item
        bool roomForItem(const InventoryItem *item);

        // Checks whether there is room for a given item after it has been cooked
        bool roomForCookedItem(const InventoryItem *item);

        // Checks whether there is room for a given item aftr it has been crushed
        bool roomForCrushedItem(const InventoryItem *item);

        // Takes some items from a slot.
        // If there are not enough, takes as many as it can.
        // Returns NULL if couldn't take any.
        InventoryItem * takeItem(u32 i, u32 count);

        // find a stack containing an item
        InventoryItem *findItem(content_t item, u16 *item_i = NULL);

        // Decrements amount of every material item
        void decrementMaterials(u16 count);

        void print(std::ostream &o);

        void addDiff(u32 index, InventoryItem *item) {m_diff.add(m_name,index,item);}
        InventoryDiff &getDiff() {return m_diff;}

private:
        core::array<InventoryItem*> m_items;
        u32 m_size;
        std::string m_name;
        std::map<content_t,bool> m_allowed;
        std::map<content_t,bool> m_denied;
        bool m_stackable;
        InventoryDiff m_diff;
}

Note: there is no explicit constructor for m_list. The default constructor probably was run. At least the data and allocated fields were set NULL.
Note: m_lists size just returns the used field.
Note: The loop has no guard, it just relies upon size().
Note: This core: may be part of the irrlicht library, however I have seen the similar kinds of problems with a std: vector.
Note: this is the first time, in weeks of running this program, that I have seen this particular segfault.

Possibilities:
1. the library is not initializing the m_lists correctly
2. the user is required to check for empty list before looping over content, or using size(). Don't know how.
3. the user is required to initialize this item explicitly.
4. the compiler is optimizing away something that it should not.
5. Something is writing random values.

Comments based on your experience with C++ constructs and the C++ compiler please.
Please note that I can not make this segfault happen again, so I cannot "try something" and see immedidate results.

pan64 02-08-2024 02:17 AM

valgrind looks for exactly this kind of errors.


All times are GMT -5. The time now is 11:42 AM.