C++: No output for Char* when on AIX. Worked on Linux

Hi All,

I have a script (attached) that was working fine on Linux. I compiled it there using

g++ CrncyFmt.cpp -o CrncyFmt.o

When I ran it there using eg.

CrncyFmt.o 2343.565 2

I get as expected:

CharOut  = "               2,343.57"

Now we have moved to our test box which is AIX and I have compiled it using

/usr/vacpp/bin/xlC_r -q64 CrncyFmt.cpp

(The command needs to be used in this format to work with Datastage which will be calling it)

But when I try to run it using eg

./a.out 2343.565 2

it returns only

CharOut  = ""

Can anyone please help me fix the code so that it works on AIX?

Many thanks!

Lee
PS AIX Version:

Fileset                                 Actual Level        Maintenance Level
-----------------------------------------------------------------------------
bos.rte                                 6.1.4.0             6.1.0.0
 

I have no idea how you ever compiled this on linux:

crnc.cpp:64: error: 'atoi' was not declared in this scope

You need to #include <stdlib.h>

With luck this will fix the AIX error too. Undeclared external functions can break very badly on 64-bit platforms.

Hi Corona,

Thanks for the quick response. It does actually compile on both Linux and AIX ... with or without the #include <stdlib.h>

I added the stdlib.h line but it still only outputs

CharOut  = ""

Lee

---------- Post updated at 03:56 PM ---------- Previous update was at 03:45 PM ----------

By the way, I should have noted also that placing

cout << "\nCharOut1  = \"" << CharOut << "\"\n\n"; //test print output

on line 239 before the final return DOES successfully give the right output. So something appears to be going wrong in the way the CrncyFmt function is being called by the main function or the way the CharOut is returned.

Lee

Not here it doesn't. In C++, undeclared externals are a flat-out error. At the very least it should be a warning, which you the programmer should treat as an error because using undeclared externals indeed mess up very badly on many platforms.

Ahah... When your function returns, the object is no longer in memory, so the memory the string was stored in is no longer allocated and may be overwritten with garbage at any time. It's a sneaky form of returning a pointer to a local variable, disguised enough that the compiler can't warn you about it.

You should pass a buffer into the function to copy the string into instead.

void function(char *outstr, const char *instr1, const char *instr2)
{
        strcpy(outstr, "hello world");
}

int main(void)
{
        char buf[512];

        function(buf, str1, str2);

        printf("Output was %s\n", buf);
}

Hi Corona,

Thanks again for both the note on undeclared externals (still not sure why I get no warning or error) and the solution.

Unfortunately I need my CrncyFmt function to return a Char*, not be void as it will eventually be run standalone.

Alternatively if it makes sense to make CrncyFmt a wrapper function with the original signature it had and put the majority of the code into a void function that would be fine too. Will that work?

Lee

---------- Post updated at 04:20 PM ---------- Previous update was at 04:15 PM ----------

Ok, so seeing your code, I decide to try the following as the final lines:

 strcpy(CharIn, CharOut);
        return CharIn;

Which works. Is it going to cause any issues to overwrite the input value like that?

Yes. You're overwriting not just your input but all kinds of data beyond it you shouldn't be, corrupting main()'s argument array.

If you really, really need to return a char * (why can't you pass a buffer into a standalone? everything else does, that's how it's supposed to work) you can return a pointer to a static local variable.

char *function(const char *wtf)
{
        char buf[512];
        strcpy(buf, wtf);
        return(buf);
}

...but this is discouraged because it will always return the same buffer.

char *a=function("abc");
char *b=function("def");

// both A and B now point to "def"

Ok, I'll take your word for that, it sounds bad.

The reason I need to return a char, not void, is because it's run from within Datastage, which expects functions to have a return value. So for example a derivation for an output will be CrncyFmt("123.456","2"). There is no option to specify void functions.

I tried changing the signature to

char *CrncyFmt (const char* CharIn, const char* CharDecPrecNum)

but then compilation failed:

"CrncyFmt.cpp", line 63.24: 1540-0258 (S) A return value of type "char *" cannot be initialized with an expression of type "const char *".

Adding Const to the function return type and in the main function worked but then still returned an empty string from main. The environment is not fully functional yet so I can't test this from within Datastage, perhaps it would work.

It means what it says it means. You're trying to return a const char * as a char *.

I have no idea what you're doing now, but whatever it is, you shouldn't be doing that. Are you at least returning a static local buffer yet?

Just take the orginal and change the return statement at the end to this:

return( ::strdup( StrOut.c_str() ) );

Just make sure you call ::free() on the returned pointer. Not delete - ::free().

Passing in a buffer means you have to deal with the off chance of getting a string longer than you buffer - you can't ignore that.

Corona, thanks for your reply and help, unfortunately my almost non-existent C++ knowledge means I'm sure I've misunderstood you and am not doing it right.

Achenle: I tried your solution and it seems to work fine. Have not yet been able to test from within Datastage yet, but thanks very much for you help!

Don't apologize, I don't expect you to know everything. But I can't correct your code if I can't see it from here either! You have to post it! :slight_smile:

Will Datastage be able to free() the resulting memory after? if not, your application will leak memory. I suspect it would not, hence why I was suggesting static local variables instead.

Hi Corona,

Thanks again for getting back to me. My final code is as achenle suggested: as per my original attachment with that single change. This seems to work fine and I have checked the Datastage forums and verified that it handles memory allocation to ensure no leaks.

Cheers,

Lee