Error while accessing const char* in struct within a class - c++

I am using this snippet in one of my classes and I got a behavior, that I cannot explain properly. There are two different outputs, the one works on my simulation with the QtCreator, the other does not work on my embedded system.
Header:
typedef struct
{
int anInt;
const char* aString;
} aStruct;
class Foo
{
...
private:
...
static const aStruct STRUCT_ARRAY[];
static const char* A_STRING;
static const char* ANOTHER_STRING;
}
CPP - Implementation
const char* Foo::A_STRING = "HelloStackOverflow";
const char* Foo::ANOTHER_STRING = "ByeStackOverflow";
const aStruct Foo::STRUCT_ARRAY[] =
{
{ 0, A_STRING},
{ 1, ANOTHER_STRING},
};
If I want to access now the string within my class via printf the application crashes on my embedded machine (printf(" ... %s ...", STRUCT_ARRAY[0].aString). Using this in QtCreator with qDebug << STRUCT_ARRAY[0].aString it totally works fine.
It also works if I replace the const array entry directly with the string A_STING -> "HelloStackOverflow". What am I missing here? In my understanding, the compiler just replaces the the entry within the array with the address the pointer points too.
I am using the Atmel AVR 32-bit toolchain.
/edit: it also crashes with strcat (besides the printf problem)
/edit2: what I tried so far (did not solve it yet)
played around with the const-ness of the elements (especially of the array)
Order of elements at the header
Changed optimizer level (0|1|2|3|s)

Related

Warning unused variable using typeid

I have written a small wrapper for typeinfo to get the typecode of a variable at compile time more easily:
template<typename DataType>
class TypeInfo
{
public:
static const char* typecode()
{
DataType TypedVariable = 0;
const char* code = typeid(TypedVariable).name();
return(code);
};
};
I use it like this:
const char* code = TypeInfo<float>::typecode();
It compiles perfectly fine and works as expected, but I am getting the warning
src/common.hh(153): warning: variable "TypedVariable" was set but never used
detected during:
instantiation of "char TypeInfo<DataType>::typecode() [with DataType=r32]"
...
I am wondering why "calling" typeid() on a variable does not count as using it. I know that it is a defined keyword, but still I am irritated that getting the type of a variable does not count as using it.
The compilation is done using nvcc of CUDA 9.2. Maybe it is a CUDA specific thing?
Thanks for any help :)
//edit:
I made a mistake by not returning the full char* because I use only normal types! Thanks for making me aware of the typo! I also added the template definition. I forgot to copy that over!
Because you don't use the value of TypedVariable. You just use its type (and you can get it's type by rewriting your initialization as:
char const * const code = typeid(DataType).name();

Using Global Variables in MCJIT

I’m trying to JIT compile some functions in an existing C/C++ program at runtime, but I’m running into some trouble with global variable initialization. Specifically, the approach I’ve taken is to use Clang to precompile the program into IR bitcode modules in addition to the executable. At runtime, the program loads the modules, transforms them (program specialization), compiles and executes them. As it turns out, I have some global variables that get initialized and modified during execution of the “host” program. Currently, these globals are also getting initialized in the JIT compiled code, whereas I’d like them to be mapped to the host global variables instead. Can someone help me with this?
A small repro is excerpted below. Full source code is here. The file somefunc.cpp gets precompiled during build, and is loaded in the main() function in testCompile.cpp. The global variable xyz is initialized to point to 25 in somefunc.cpp, but I’d like it to point to 10 as in main() instead. In other words, the assertion in main() should succeed.
I tried a few different ways to solve this problem. The ChangeGlobal() function attempts (unsuccessfully) to achieve this updateGlobalMapping(). The second, more hacky approach uses a new global variable initialized appropriately. I can get this latter approach to work for some types of globals, but is there a more elegant approach than this?
//————— somefunc.h ————————
extern int *xyz;
//—————— somefunc.cpp ——————
int abc = 25;
int *xyz = &abc;
int somefunc() {
return *xyz;
}
//—————— testCompile.cpp ——————
class JitCompiler {
public:
JitCompiler(const std::string module_file);
void LoadModule(const std::string& file);
template <typename FnType>
FnType CompileFunc(FnType fn, const std::string& fn_name);
void ChangeGlobal();
private:
std::unique_ptr<LLVMContext> context_;
Module *module_;
std::unique_ptr<ExecutionEngine> engine_;
};
void JitCompiler::ChangeGlobal() {
// ----------------- #1: UpdateGlobalMapping -----------------
//auto g = engine_->FindGlobalVariableNamed("xyz");
//engine_->updateGlobalMapping(g, &xyz);
//assert(engine_->getGlobalValueAddress("xyz") == (uint64_t) &xyz);
// ----------------- #2: Replace with new global ————————
// ------- Ugly hack that works for globals of type T** ----------
auto g = engine_->FindGlobalVariableNamed("xyz");
Constant *addr_i = ConstantInt::get(*context_, APInt(64, (uint64_t) xyz));
auto addr = ConstantExpr::getIntToPtr(
addr_i, g->getType()->getPointerElementType());
GlobalVariable *n = new GlobalVariable(
*module_,
g->getType()->getPointerElementType(),
g->isConstant(),
g->getLinkage(),
addr,
g->getName() + "_new");
g->replaceAllUsesWith(n);
n->takeName(g);
g->eraseFromParent();
}
int main() {
xyz = new int (10);
JitCompiler jit("somefunc.bc");
jit.ChangeGlobal();
auto fn = jit.CompileFunc(&somefunc, "somefunc");
assert(somefunc() == fn());
}
A better approach is the combination of the two you presented, that is, to create a new global with external linkage mapped to &xyz and substitute it for the original:
auto g = engine_->FindGlobalVariableNamed("xyz");
GlobalVariable *n = new GlobalVariable(
g->getType()->getPointerElementType(),
g->isConstant(),
ExternalLinkage
nullptr,
g->getName() + "_new");
engine_->updateGlobalMapping(n, &xyz);
g->replaceAllUsesWith(n);
n->takeName(g);
g->eraseFromParent();

Mixing pointers to const structs in C++ classes -- declaring a struct on the arguments list?

I'm developing for an embedded hardware using C++ and I often use pointers to const (ROM) structs to minimize the object sizes.
When I get a pointer passed to my class constructor, I want the compiler to create another ROM object based on the one I passed but with one or two arguments changed and just then call the parent class constructor (Display_Element). Any ideas of how this could be done?
Since a const string can be declared within a parameter list I though possibly there could be a way of also declaring a const struct within a parameter list.
I wanted to do something like this, (which is illegal in C++)
Button::Button(const Colors_const* ecc, const Display_element_const* edc, const Element_const* eec, char* elabel,
Display_element* eparent, Screen* escreen) :
Display_element(ecc, cc,Display_element_const {
edc->xi+200,
edc->xf,
edc->yi,
edc->yf,
edc->font_size,
edc->image,
edc->image_x_offset,
edc->image_y_offset,
edc->label_x_offset,
edc->label_y_offset,
edc->mouse_down_ptr,
NULL,
edc->largura_borda_externa,
edc->borda_panel
},
eec,elabel,eparent,escreen) {
flags.largura_borda = 2;
//flags.largura_borda_externa = 3;
flags.borda_light_shadow = true;
flags.sliding_text = true;
flags.dont_paint_on_click = false;
}
Thanks
Well, it seems what I want to do is really illegal and can't be done in C. But philosophically I keep asking myself: if I can allocate a const char[n] written inside a parameter list such as fn(...,"The brow dog",...) why not a way to allocate a const struct the same way? If someone knows the answer, please post!
The workaround I found is to do it the canonical way: declare a const struct and then later assign the appropriate pointer to the struct (something I wanted to be done inside Display_element function on the first place). It solves my problem, but not the conceptual question I've been trying to formulate...
const Display_element_const new_ec = {
edc->xi+200,
edc->xf,
edc->yi,
edc->yf,
edc->font_size,
edc->image,
edc->image_x_offset,
edc->image_y_offset,
edc->label_x_offset,
edc->label_y_offset,
edc->mouse_down_ptr,
NULL,
edc->largura_borda_externa,
edc->borda_panel
};
Button::Button(const Colors_const* ecc, const Display_element_const* new_edc, const Element_const* eec, char* elabel,
Display_element* eparent, Screen* escreen) :
Display_element(ecc, edc,eec,elabel,eparent,escreen) {
//previously dc = edc, assigned inside Display_element fn
dc = &new_ec;

Is something wrong with wrapper classes for C string functions?

I have some C++ code written in C-style.
For some reasons I can't use C++ string and IO libraries, so for strings handling I should use only functions like sprintf, itoa, etc.
I want to replace C-style which requires temporary buffers
char buf[12];
itoa(x, buf, 16);
set_some_text(buf);
by the following code
class i2a
{
public:
explicit i2a(int value) { ::sprintf(buf, "%d", value); }
operator const char* () const { return buf; }
private:
char buf[12];
};
// usage:
set_some_text(i2a(x));
(Such classes can be written for char<->wchar_t convertions, etc.)
I see some cases when such classes will be dangerous:
For example, one can write
const char* someMeaningfulName = i2a(x);
// the right code should be i2a someMeaningfulName(x); or i2a someMeaningfulName = i2a(x);
set_some_text(someMeaningfulName);
In more complex case, a function which accepts text will not copy it, but will save pointer to it somewhere. For example it may be
class Foo { .... const char* p; };
Foo f(const char* text) { ... foo.p = text; return foo; }
it can be really unobvious, unlike const char* variable.
Is there a way to make such classes more secure?
Upd: why not std::string, boost::lexical_cast, boost::format, etc :
The code should work when compiled with -fno-except (C++ exceptions disabled - no throw, no stack unwinding). Also it should keep working on low memory conditions.
std::string, streams uses heap-allocated memory and at least throws bad_alloc.
When we have no free heap memory, usually we still have some kilobytes of stack (for example to write to user that we are out of memory and then make proper cleanup).
ATL and MFC String Conversion Macros are also written in this way. Calling the constructor directly like i2a(x) will create a temporary object that will live until the function to which it is passed is complete. So here: do_some(i2a(x)), the temporary object will be there until do_some() is complete.
Refer the Example section (example 2) of this msdn document
Here,
const char* someMeaningfulName = i2a(x);
set_some_text(someMeaningfulName);
This will not work as, the temporary object will be freed on the first statement itself. someMeaningfulName will be garbage. If you feel that as lack of security, all I can say is:
That's how Microsoft does it!
You will always get somewhere into troubles if you use const char* for your local variables.
You will have the same with const char* someMeaningfulName = std::string("foo").c_str();
If you can you should declare your local variable like this :
i2a someMeaningfulName(x);
set_some_text(someMeaningfulName);
You can also consider adding a copy constructor to i2a to avoid sharing the buffer between two instances.

Static structure initialization with tags in C++

I've searched stackoverflow for an answer but I cannot get something relevant.
I'm trying to initialize a static structure instance with initial values by specifying their tags, but I get an error at compilation time:
src/version.cpp:10: error: expected primary-expression before ‘.’ token
Here's the code:
// h
typedef struct
{
int lots_of_ints;
/* ... lots of other members */
const char *build_date;
const char *build_version;
} infos;
And the faulty code:
// C
static const char *version_date = VERSION_DATE;
static const char *version_rev = VERSION_REVISION;
static const infos s_infos =
{
.build_date = version_date, // why is this wrong? it works in C!
.build_version = version_rev
};
const infos *get_info()
{
return &s_infos;
}
So the basic idea is to bypass the "other members" initialization and only set the relevant build_date and build_version values.
This used to work in C, but I can't figure out why it won't work in C++.
Any ideas?
edit:
I realize this code looks like simple C, and it actually is. The whole project is in C++ so I have to use C++ file extensions to prevent the makefile dependency mess ( %.o: %.cpp )
The feature you are using is a C99 feature and you are using a C++ compiler that doesn't support it. Remember that although C code is generally valid C++ code, C99 code isn't always.
The following example code defines a struct in what I consider a more C++ way (no need for typedef) and uses a constructor to solve your problem:
#include <iostream>
#define VERSION_DATE "TODAY"
#define VERSION_REVISION "0.0.1a"
struct infos {
int lots_of_ints;
/* ... lots of other members */
const char *build_date;
const char *build_version;
infos() :
build_date(VERSION_DATE),
build_version(VERSION_REVISION)
{}
};
static const infos s_infos;
const infos *get_info()
{
return &s_infos;
}
int main() {
std::cout << get_info()->build_date << std::endl;
std::cout << get_info()->build_version << std::endl;
return 0;
}
I believe this was added as a feature in C99, but has never been a standard feature in C++.
However, some compilers probably offer it as a non-standard language extension.
I see that this is part of CPP 20 standard now. It is called Designated initializers.
T object = { .des1 = arg1 , .des2 { arg2 } ... }; (3) (since C++20)
T object { .des1 = arg1 , .des2 { arg2 } ... }; (4) (since C++20)