I’ve been trying to switch over my code to being object oriented, with objects with methods for all of the main mechanisms instead of the large number of separate global variables I’ve been using previously.
It built fine, but upon uploading the code, it didn’t work. That isn’t that surprising, but I have no idea what the error message I got means, and how it displayed on the brain seems rather concerning.
Initialize didn’t run, I have a cout at the very beginning as a test and it didn’t trigger, so whatever’s going wrong is occurring before there. It also isn’t a problem with the brain, I don’t think, because my old code still runs fine.
I’m not a C++ expert, so pointers seems like an initial culprit. Okapi chassis builders don’t seem to work when used outside of one of the competition functions, so for the initialization of my custom objects I created global pointers, and then assigned them to my objects declared in initialize. Since the very first line of initialize isn’t running though, I don’t see how this interaction could cause any problems here, since the declarations never even run.
Any ideas? I can share my code if I need to, although I’m doing a turret bot so I don’t really want to share all the math there.
and its variants (monolith.elf, hot.package.elf), which is something I saw posted as a debugging tool for this kinda thing, but it didn’t run for some reason:
I’ve also never seen an error message on a brain have messed up characters like mine consistently does with this. I’ve reuploaded my old code, and it didn’t have this issue, but I’ll try swapping out the brain next time I have access to a replacement just in case the brain is at fault for that weird behavior.
Separate from its cause in my code specifically, does anyone know what the error message I got for running my code is even saying? What is “Exception occurred: basic_string::_M_create”?
Knowing what kind of process is going wrong would make trying to comb through the code to find the problem much easier.
I’m assuming you installed PROS through VSCode? If so, you should not run the command “%PROS_TOOLCHAIN%\bin\arm-none-eabi-addr2line” -faps -e .\bin\cold.package.elf. Try running this command IN THE PROS INTERGRATED TERMINAL instead: arm-none-eabi-addr2line -faps -e .\bin\cold.package.elf . Afterwards, you can copy each stack trace in to identify where it is going wrong. If you receive a bunch of question marks (it will look something like ? : ?? : ), then try using .\bin\hot.package.elf instead of the cold package. Finally, if that also doesn’t work, you can disable hot/cold linking by modifying your Makefile, rebuild and upload the project, and then try the stack traces on .\bin\monolith.elf.
However, the image you showed is not what data abort exceptions normally look like. Normally, your stack trace would be a bit longer and the brain screen would clearly say “Data Abort Exception”. Can you remember what change you made to the code before this happened? That is a likely what caused it.
If you haven’t already, I would try cleaning and rebuilding your project, as well as removing the program from the brain before re-uploading.
And as James said, it does appear to be something with std::string, so that is somewhere you should look at as well.
Actually went as far as replacing the brain because of some issues we were having, and the issue persisted.
I managed to isolate the specific line of code causing the issue:
Intake intake = *intake_pointer;
Dereferencing my other objects caused no issues, and, what do you know, one of the things in the intake class but not the others is a string. Is there something wrong with this constructor?
I’m only on mobile right now, so it’s hard to sort through all your code. Where is intake_ptr coming from? I don’t see it in the main or intake header files, so it’s not clear to me where (& how) that pointer is being declared and passed.
Make sure it’s not getting assigned from a local variable via a function that’s gone out of scope. Getting something funky stack-wise can sometimes point to the wrong variables when a crash happens (memory maps can only be so accurate).
Okay, because this was going to keep me from sleeping, I managed to dig through and find where you’re getting the pointer assigned, and sure enough, you’re declaring your class instances in a function that’s then going out of scope (finishes the function and leaves).
You need to make global instances of Chassis, Intake, and whatever the third class in initialize() is, and then you can assign the pointers as you are in initialize(), because the classes have already been allocated globally. I’ll put a virtual $5 on the table that you move those to global and your stack crash (from that at least) goes away.
You know, that makes a lot of sense. Okapi has some special rules with controllers having their internal tasks persist after the task that calls them ends if that task is initialize, but that isn’t the same thing as keeping the objects in scope, and definitely not if they’re embedded in other objects.
I didn’t have the objects themselves global because when I’ve tried to do the chassis builders and the like with okapi outside of one of the competition run functions previously it’s always broke on me. I’ll go back to a multiple stage construction approach, where I declare the objects globally, and then define those problematic elements in initialization, which, if I understand how scope for these kinds of things works correctly, should keep everything in scope after initialize ends.
The compiler does appear to let me not declare some things in the constructor, but for others it complains (saying they don’t have default constructors). Luckily, those errors aren’t present for the okapi controllers, so I should be able to make the objects global without too much trouble.
Won’t be able to verify that this is the solution until Tuesday, but I think it probably is. Thanks!
I knew it had something to do with those darn pointers… It definitely threw me off that the problematic lines of code aren’t even running, but adding or removing them determines if the errors occur, so I guess it’s just caught preemptively, if not at build time.
If you’re running into issues with things at initialization time, try to put them in their own function for setting/getting that you call after initialization is done. You may need to initialize some objects with the bare minimum first, and then come back slightly later to set the other parameters. For instance, maybe you only assign a motor the port, and later you set the forward/reverse mode, cartridge, etc.
One other thing I meant to mention in my post last night, your other two classes are likely just getting lucky that they’re not getting trampled off the stack/heap as well. Or maybe they are, and you just weren’t able to notice it, because your Intake instance was the first one getting nuked. Compilers and memory managers are fun things…
Well, after doing that I no longer get any error messages. However, initialize doesn’t appear to be running either. I put console output as the very first line of it, and also after a 1 second delay, and neither ran. What could cause one of the competition-run functions not to run like that without raising any error messages?
Is that change on a branch in the GitHub repo, so the whole thing can be looked at?
It’s entirely possible that something is hanging up in a class initializer/constructor somewhere, so you might try adding some printouts into various constructors and see what you get.
I see now it’s checked into master. I will try to take a look tomorrow afternoon when I’m able to pull it up.
Am I missing a main function somewhere? I need to compare to the base competition template, something fundamental seems off, but again, doing this on mobile .
There isn’t a main function anywhere, but there isn’t by default either. I’ve never had one, even in working versions. Pros is handling all that stuff on its own, I don’t know how to access it.
The solution to this last error was actually quite simple. Initialize was running, it just wasn’t processing the console output. Don’t know if this is generally a fact I was unaware of in C++, or just a quirk of the pros terminal, but console output isn’t actually processed until a std::endl is ended, which I hadn’t bothered with. The program still doesn’t work perfectly, but it’s at a level where I can understand what’s going on and can handle it on my own. Thanks for all the help!