c++ using of iconv on Windows with Mingw compiler - c++

Good time of day!
I compiled this code with g++ 4.7.2 on Ubuntu successfully, but I have problems with compiling it on Windows with Mingw.
Simplified Code:
size_t string_length=some_size;
char arr_symb[string_length+1];
char *outputde=arr_symb;
iconv_t type=iconv_open("UTF-8","WINDOWS-1251");
char output[some_size];
char *p1=arr_symb;
char *p2=output;
if ( iconv(type, &p1,&string_length, &p2, &output_length ) == -1 )// here
// is mistake, it doesn't like pointers p1 and p2 but I wonder why
log_info("something went wrong");
On Linux with G++ it can be compiled and works fine as it should. With Mingw I get errors:
I wonder, if it works fine with g++ , why does mingw treat it like it's mistaken?
Thanks in advance!
ADDITION
My Mingw version is 4.4.0
GCC version is 4.7.2

Thanks all for your attention, problem is solved, but it's all strange to me (it's still unclear )
Although the function has such prototype,
With MinGW it should be called so:
So, the problem is that input string for MinGW should be passed as constant (also it doesn't have such prototype).

See these declarations:
int a[10];
int* b = malloc(10 * sizeof(int));
Looks and feels the same, but:
A pointer to an array of ints (*b) is NOT the same as an array of ints (a)! So a pointer to an array (*) is also not the same as a pointer to a pointer (**)!
The dereferencing for the pointer needs one more level!

Related

Solaris' stdlib.h functions implemented by C++ libs?

I am struggling with a port of an open-source tool to Solaris. Most things work, cmake/pkg-config/etc. are there, dependencies are found, gmake works, compiler and linker calls look all fine and tren, boom:
Undefined first referenced
symbol in file
std::qsort(void*, unsigned int, unsigned int, int (*)(const void*, const void*)) ...
This part I don't understand. At the first glance, std::qsort does not make sense, it is supposed to be part of C library, not STL. So I looked into stdlib.h and found a list of things like using std::sort; and dozens of other standard functions like free, malloc, atoi, etc., redirected in case of C++ context.
What is Oracle doing there and why? Which library am I supposed to link with if they do redirect it like this? Or why does CC command not pull that in automatically like GCC does?
I tried adding -lstdc++ but no luck.
Alternatively, the plain libc versions seem to be defined in <iso/stdlib_c99.h> (or <iso/stdlib_iso.h>). Is it legal to include one of those headers directly or will this wreak other random havoc at link time?
Edit:
since there are multiple suspicions of the build system weirdness, here is the basically the linking call from the gmake execution:
/opt/developerstudio12.6/bin/CC -std=c++11 -xO3 -DNDEBUG <i.e. bunch of object files> -o ../systest -L/opt/csw/lib/64 -lintl
I cannot see anything special there and I expect CC to figure out what to link to get the obligatory functionality.
The rule is that #include <xxx.h> puts names into the global namespace and is allowed to also put them in std. Conversely, #include <cxxx> puts names into std and is allowed to also put them into the global namespace. In practice, this means that there are two approaches to implementing the functions from the standard C library in C++: declare the standard C library names in the <xxx.h> headers and hoist those declarations into std in the cxxx headers, or declare the names in std in the headers and hoist those declarations into the global namespace in the <xxx.h> headers. With the former approach, the name of the function will be qsort; with the latter, it will be std::qsort. Either way, that error message usually indicates a setup problem with the compiler. The linker isn’t finding the standard library.
This compile command
/opt/developerstudio12.6/bin/CC -std=c++11 -xO3 -DNDEBUG ...
will produce a 32-bit executable. Per the Oracle CC man page:
On Oracle Solaris, -m32 is the default. On Linux systems supporting 64-bit programs, -m64 -xarch=sse2 is the default.
But this library option
-L/opt/csw/lib/64
is searching a directory full of 64-bit libraries.
Either add -m64 to the compile command or use the 32-bit library path.
Update
The question almost certainly would be answerable had it included the full error message, which is almost certainly something like this:
CC -g qsort.cc -o qsort
"qsort.cc", line 15: Error: Could not find a match for std::qsort(int[4], unsigned, unsigned, int(void*,void*)) needed in main(int, char**).
"/usr/include/iso/stdlib_iso.h", line 184: Note: Candidate 'std::qsort(void*, unsigned, unsigned, extern "C" int(*)(const void*,const void*))' is not viable: argument '4' can't be converted from 'int(void*,void*)' to 'extern "C" int(*)(const void*,const void*)'.
"/usr/include/iso/stdlib_iso.h", line 187: Note: Candidate 'std::qsort(void*, unsigned, unsigned, int(*)(const void*,const void*))' is not viable: argument '4' can't be converted from 'int(void*,void*)' to 'int(*)(const void*,const void*)'.
This code works just fine when compiled with Oracle Developer Studio 12.6 on Solaris 11.4:
#include <stdlib.h>
int compare( const void *p1, const void *p2 )
{
int i1 = *( ( int * ) p1 );
int i2 = *( ( int * ) p2 );
return( i1 - i2 );
}
int main( int argc, char **argv )
{
int array[ 4 ] = { 5, 8, 12, 4 };
qsort( array, sizeof( array ) / sizeof( array[ 0 ] ),
sizeof( array[ 0 ] ), &compare );
}

Declare C++ array type with dynamic size works fine in Linux, but not Windows [duplicate]

This question already has answers here:
Why aren't variable-length arrays part of the C++ standard?
(10 answers)
Closed 4 years ago.
With recent gcc versions, I can declare dynamic-sized array data types like this:
#include <stdio.h>
int main() {
int u;
scanf("%d", &u);
using my_type = int[u];
printf("size of my_type: %d\n", sizeof(my_type));
return 0;
}
This compiles with gcc successfully, and works fine in Linux. Enter 5 for example as input, this will print 20.
But with Windows compiler cl.exe or VS2015 itself, I receive compile error:
error C2540: non-constant expression as array bound
How can I solve this?
This is not valid portable C++. This is a C99 extension (Variable Length Array) to GCC that is not available with any Visual Studio version.

copying function pointer throws error in one function pointer

I have cjson code (https://github.com/kbranigan/cJSON/blob/master/ ) , it compiles well when I compile on the linux pc .
but when I compile for some embedded platform it throws error at
if (!hooks) { /* Reset hooks */
cJSON_malloc = mem_alloc; // its equal to gcc malloc for the embedded compiler
cJSON_free = mem_free; // its equal to gcc free
}
The error is Undefined reference to mem_alloc , and mem_free
but if I call the function like below
char* data = (char*) mem_alloc(32);
it compiles well ..
compiler is xtensa compiler(xt-xcc)
isn't it right way to assign ?

How to trace out why gcc and g++ produces different code

Is it possible to see what is going on behind gcc and g++ compilation process?
I have the following program:
#include <stdio.h>
#include <unistd.h>
size_t sym1 = 100;
size_t *addr = &sym1;
size_t *arr = (size_t*)((size_t)&arr + (size_t)&addr);
int main (int argc, char **argv)
{
(void) argc;
(void) argv;
printf("libtest: addr of main(): %p\n", &main);
printf("libtest: addr of arr: %p\n", &arr);
while(1);
return 0;
}
Why is it possible to produce the binary without error with g++ while there is an error using gcc?
I'm looking for a method to trace what makes them behave differently.
# gcc test.c -o test_app
test.c:7:1: error: initializer element is not constant
# g++ test.c -o test_app
I think the reason can be in fact that gcc uses cc1 as a compiler and g++ uses cc1plus.
Is there a way to make more precise output of what actually has been done?
I've tried to use -v flag but the output is quite similar. Are there different flags passed to linker?
What is the easiest way to compare two compilation procedures and find the difference in them?
In this case, gcc produces nothing because your program is not valid C. As the compiler explains, the initializer element (expression used to initialize the global variable arr) is not constant.
C requires initialization expressions to be compile-time constants, so that the contents of local variables can be placed in the data segment of the executable. This cannot be done for arr because the addresses of variables involved are not known until link time and their sum cannot be trivially filled in by the dynamic linker, as is the case for addr1. C++ allows this, so g++ generates initialization code that evaluates the non-constant expressions and stores them in global variables. This code is executed before invocation of main().
Executables cc1 and cc1plus are internal details of the implementation of the compiler, and as such irrelevant to the observed behavior. The relevant fact is that gcc expects valid C code as its input, and g++ expects valid C++ code. The code you provided is valid C++, but not valid C, which is why g++ compiles it and gcc doesn't.
There is a slightly more interesting question lurking here. Consider the following test cases:
#include <stdint.h>
#if TEST==1
void *p=(void *)(unsigned short)&p;
#elif TEST==2
void *p=(void *)(uintptr_t)&p;
#elif TEST==3
void *p=(void *)(1*(uintptr_t)&p);
#elif TEST==4
void *p=(void *)(2*(uintptr_t)&p);
#endif
gcc (even with the very conservative flags -ansi -pedantic-errors) rejects test 1 but accepts test 2, and accepts test 3 but rejects test 4.
From this I conclude that some operations that are easily optimized away (like casting to an object of the same size, or multiplying by 1) get eliminated before the check for whether the initializer is a constant expression.
So gcc might be accepting a few things that it should reject according to the C standard. But when you make them slightly more complicated (like adding the result of a cast to the result of another cast - what useful value can possibly result from adding two addresses anyway?) it notices the problem and rejects the expression.

Error with variable array size using the visual C++ compiler (Visual Studio 2010). How to circumvent this issue?

I am experiencing some troubles compiling a c++ file that worked well as a previous build under GCC.
The issue is, I am using vectors of variable array size:
unsigned int howmany;
std::vector<int>* array_adresses[howmany];
I am currently using the Visual-Studio 2010 C++ compiler to built Matlab 64-bit Mex-Files.
Since VC++ won't allow me to use arrays whose size is unknown at compile time, I am receiving the following error messages:
error 2057: constant expression expected
error 2466:
error 2133: unknown size
Is there any way to build the 64 bit mex file using a GCC-compiler option or build it with a different 64-bit compiler under Matlab?
Thanks in advance!!
howmany needs to be constant, and needs to be a defined amount, like so:
const unsigned int howmany = 5;
std::vector<int>* array_adresses[howmany];
Or you can define it dynamically like this:
unsigned int howmany = 5;
std::vector<int>* array_adresses = new std::vector<int>[howmany];
C++ standard doesn't allow variable-length arrays. Lets take this code:
int main(int argc, char *argv[])
{
int a[argc];
return 0;
}
This compiles fine with g++ foo.cpp, but fails if you require a strict standard compliance.
g++ foo.cpp -std=c++98 -pedantic:
foo.cpp: In function ‘int main(int, char**)’:
foo.cpp:8: warning: ISO C++ forbids variable length array ‘a’
You should use vector<vector<int> *> or vector<int> ** instead as others already suggested.
Simply replace
int ptr[howmany];
with
vector<int> ptr(howmany);
to obtain also automatic deallocation at the end of the scope.