return a string array

C

collinm

hi

i would like to return a string

Code:
char *readFile(char *tmp_dir_led, char *directory, char *filename)
{
    FILE *fp;
    char line[LINE_MAX];
    snprintf(tmp_mnt_dir_led, sizeof(tmp_mnt_dir_led),"%s/%s",
directory,filename);
    fp = fopen(tmp_mnt_dir_led, "r");
    if(fp!=NULL)
    {
        fgets(line, LINE_MAX, fp);
    }

    return line;
}

in my block main i do:

printf("%s\n",readFiletmp_mnt_dir_led, mnt_dir_led,
"B_L1_HLD_GRN_NOR_Run_Counter.txt"));

i see some crap character

are there any way to do resolve this problem in C?

thanks
 
W

Walter Roberson

i would like to return a string
char *readFile(char *tmp_dir_led, char *directory, char *filename)
{
FILE *fp;
char line[LINE_MAX];
return line;
}

line is an variable of storage class "automatic". Usually that means
it will be allocated on the stack. You then return line, which will
silently decay from being an array to become a pointer to the first
element of the array. But when that pointer value is used outside
the routine, it points to something that logically no longer exists
(the automatic storage.)

If you want to return a generated character array, you will have to
malloc() [or equivilent] space for the array and return it. And
remember to free() the space afterwards.
 
R

Richard Bos

collinm said:
char *readFile(char *tmp_dir_led, char *directory, char *filename)
{
FILE *fp;
char line[LINE_MAX];
snprintf(tmp_mnt_dir_led, sizeof(tmp_mnt_dir_led),"%s/%s", directory,filename);

Apart from the answer by Eric, you need to realise that this is also a
bug. sizeof on a pointer object gives you the size of the pointer
itself, not of the area it points at. Most likely this means that even
if you solve the problem with the return value, you will not be able to
open the file because the file name gets truncated; if you pass in a
pointer to an excessively short char area (or have excessively large
pointer types...), you may cause undefined behaviour by writing past the
end of the name buffer.

Richard
 
C

collinm

Walter said:
i would like to return a string
char *readFile(char *tmp_dir_led, char *directory, char *filename)
{
FILE *fp;
char line[LINE_MAX];
return line;
}

line is an variable of storage class "automatic". Usually that means
it will be allocated on the stack. You then return line, which will
silently decay from being an array to become a pointer to the first
element of the array. But when that pointer value is used outside
the routine, it points to something that logically no longer exists
(the automatic storage.)

If you want to return a generated character array, you will have to
malloc() [or equivilent] space for the array and return it. And
remember to free() the space afterwards.

ok i need to create a dynamic array in the function and free it outside
the function
 
C

collinm

i do:

char tmp_mnt_dir_led[75];

if(!(mnt_dir_led = getenv("LED_DISPLAY_DIR")))
{
printf("%s - Incapable de lire la variable: LED_DISPLAY_DIR\n",
strerror(errno));
return 1;
}
 
C

CBFalconer

collinm said:
.... snip ...

.... snip ...

ok i need to create a dynamic array in the function and free it
outside the function

Do I conclude that Roberson has finally corrected his quote char,
and can come off my PLONK list? The other possibility is that you
have corrected his quotes.
 
J

Joona I Palaste

Do I conclude that Roberson has finally corrected his quote char,
and can come off my PLONK list? The other possibility is that you
have corrected his quotes.

You conclude correct. He has corrected the quote char.
 
M

Mark McIntyre

Do I conclude that Roberson has finally corrected his quote char,

he seems to have changed it, yes. For which I want to thank him for
reconsidering the views expressed by several others.
and can come off my PLONK list?

Thats up to you !
 
C

CBFalconer

Mark said:
he seems to have changed it, yes. For which I want to thank him for
reconsidering the views expressed by several others.

I will also thank him. It seems others were more persuasive than
I.
 
K

Keith Thompson

collinm said:
i do:

char tmp_mnt_dir_led[75];

if(!(mnt_dir_led = getenv("LED_DISPLAY_DIR")))
{
printf("%s - Incapable de lire la variable: LED_DISPLAY_DIR\n",
strerror(errno));
return 1;
}

The standard doesn't say that getenv() sets errno on failure (and in
fact it typically doesn't).

The only reason getenv("LED_DISPLAY_DIR") should fail is if the
environment variable isn't set, so errno wouldn't give you any useful
information anyway.
 
W

Walter Roberson

:The only reason getenv("LED_DISPLAY_DIR") should fail is if the
:environment variable isn't set, so errno wouldn't give you any useful
:information anyway.

My standard is at work, so I can't check to confirm, but is
it certain that getenv() will return a pointer to an
already already-existing environment variable object? Or is it
permitted to return a copy?

The documentation I'm looking at at the moment implies that it
uses the actual pointers and that the space pointed to is modifiable
(not read-only... but you'd still have to be careful not to extend it).
I'm not sure whether that's implementation behaviour or standard-
defined behaviour though.
 
K

Keith Thompson

My standard is at work, so I can't check to confirm, but is
it certain that getenv() will return a pointer to an
already already-existing environment variable object? Or is it
permitted to return a copy?

The documentation I'm looking at at the moment implies that it
uses the actual pointers and that the space pointed to is modifiable
(not read-only... but you'd still have to be careful not to extend it).
I'm not sure whether that's implementation behaviour or standard-
defined behaviour though.

[I've taken the liberty of changing the unconventional ":" quoting
prefix to "> " above.]

C99 7.20.4.5 says:

The getenv function returns a pointer to a string associated with the
matched list member. The string pointed to shall not be modified by
the program, but may be overwritten by a subsequent call to the getenv
function. If the specified name cannot be found, a null pointer is
returned.

Since the "shall" is not in a constraint, attemptying to modify the
string would invoke undefined behavior. So an implementation is free
to return a pointer to an existing string to a unique copy, or to a
statically allocated copy.

(On one system I just tested, modifying the string affects the
environment, but of course that's a valid consequence of undefined
behavior.)
 
W

Walter Roberson

C99 7.20.4.5 says:
The getenv function returns a pointer to a string associated with the
matched list member. The string pointed to shall not be modified by
the program, but may be overwritten by a subsequent call to the getenv
function. If the specified name cannot be found, a null pointer is
returned.
Since the "shall" is not in a constraint, attemptying to modify the
string would invoke undefined behavior.

Ah, the IRIX 6.2 putenv() is -defined- such that if one modifies
the string after putenv()'ing it, then the value *is* changed.
I see though that by IRIX 6.5 the putenv() does not say anything like that.

The IRIX 6.5 putenv() talks about potential failure if the environment
cannot be expanded by malloc(), but the IRIX 6.5 getenv() does not
mention the possibility of a malloc() failure; if the two are
self-consistant the implication would be that at least for IRIX 6.5,
getenv() returns a direct pointer, not a copy of a string.

Is there anything similar that can be deduced in the C standard?
Are routines allowed failure modes such as malloc() errors
that are not listed in the standard?


This next point starts to stray a bit off-standard, but I seem
to recall seeing getenv() listed in POSIX's interrupt-safe
routines, and I don't -recall- seeing any getenv_r() or
similar name defined as a thread-safe version of getenv().
If those recollections are correct, then the implication would
be that in POSIX compliant implementations, getenv() would
be effectively constrained from malloc()'ing to produce a copy
of the string.


[These questions are apropos of your comment about failure modes
of getenv(), with me aiming towards the question "Is
out-of-memory a potential further failure mode of getenv() ?"]
 
K

Keith Thompson

Ah, the IRIX 6.2 putenv() is -defined- such that if one modifies
the string after putenv()'ing it, then the value *is* changed.
I see though that by IRIX 6.5 the putenv() does not say anything like that.

putenv() is not a standard C function. The only interface to
environment variables defined by the standard is the getenv()
function; there's no way to set an environment variable, or even to
determine which variables are set.

[...]
Is there anything similar that can be deduced in the C standard?
Are routines allowed failure modes such as malloc() errors
that are not listed in the standard?

I'm not sure. The standard's definition of getenv() seems to be
designed to allow an implementation to return an existing string
rather than allocating a copy -- and if it returned a pointer to a
malloc()ed string, the caller would have no way of knowing it needs to
be free()d, creating a memory leak.

Of course, any function can fail by running out of memory (invoking
undefined behavior).
 
C

CBFalconer

Walter said:
My standard is at work, so I can't check to confirm, but is
it certain that getenv() will return a pointer to an already
already-existing environment variable object? Or is it
permitted to return a copy?

The documentation I'm looking at at the moment implies that it
uses the actual pointers and that the space pointed to is
modifiable (not read-only... but you'd still have to be careful
not to extend it). I'm not sure whether that's implementation
behaviour or standard- defined behaviour though.

(Obnoxious non-standard quote marks corrected)
From N869:

7.20.4.4 The getenv function

Synopsis
[#1]
#include <stdlib.h>
char *getenv(const char *name);

Description

[#2] The getenv function searches an environment list,
provided by the host environment, for a string that matches
the string pointed to by name. The set of environment names
and the method for altering the environment list are
implementation-defined.

[#3] The implementation shall behave as if no library
function calls the getenv function.

Returns

[#4] The getenv function returns a pointer to a string
associated with the matched list member. The string pointed
to shall not be modified by the program, but may be
overwritten by a subsequent call to the getenv function. If
the specified name cannot be found, a null pointer is
returned.
 
R

ranveerkunal

collinm said:
hi

i would like to return a string

Code:
char *readFile(char *tmp_dir_led, char *directory, char *filename)
{
FILE *fp;
char line[LINE_MAX];
snprintf(tmp_mnt_dir_led, sizeof(tmp_mnt_dir_led),"%s/%s",
directory,filename);
fp = fopen(tmp_mnt_dir_led, "r");
if(fp!=NULL)
{
fgets(line, LINE_MAX, fp);
}

return line;
}

in my block main i do:

printf("%s\n",readFiletmp_mnt_dir_led, mnt_dir_led,
"B_L1_HLD_GRN_NOR_Run_Counter.txt"));

i see some crap character

are there any way to do resolve this problem in C?

thanks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,797
Messages
2,569,648
Members
45,380
Latest member
LatonyaEde

Latest Threads

Top