LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Memory Access Violation - C Programming (https://www.linuxquestions.org/questions/programming-9/memory-access-violation-c-programming-754168/)

richmike3 09-10-2009 09:53 AM

Memory Access Violation - C Programming
 
Hi All,

I have problem to access a memory location in 2 dimensional array.

code snippet,

function (char **strArray)
{
while (strArray != NULL)
{
printf ("%s\n", *strArray);
strArray++;
}
}

consider strArray holds 5 string value.
while (strArray != NULL) not terminating after parsing 5 string values.

What was the best check to terminate while loop after parsing 5 string values?
Is there any memory validation method available?

Thank you.

-Mr S

orgcandman 09-10-2009 10:08 AM

It is better practice to keep track of the number of elements in your array with a separate variable, and then pass both into the function.

johnsfine 09-10-2009 10:26 AM

Quote:

Originally Posted by richmike3 (Post 3677367)
consider strArray holds 5 string value.
while (strArray != NULL) not terminating after parsing 5 string values.

There is no reason it should. The value after the end of the array is not necessarily NULL.

Quote:

Is there any memory validation method available?
If there were, that wouldn't help either. The value after the end of the array is not necessarily an invalid memory address.

I'm only guessing at the context of your problem, but based on that guess, I think you should modify the original source of the array of pointers so that it always allocates one more than the number of actual pointers and always makes sure that extra one (at the end) is NULL.

If the array is static or global, the compiler/linker/loader will make sure the extra is NULL as long as you allocate one more than you initialize. But if the array is stack or heap, you need run time code to set the extra pointer to NULL.

karlatLQ 09-10-2009 01:25 PM

Try printing just one string
 
Did you get a segmentation fault when you tried to run it? That is what it looks like you would get. Have you tried to print just one string in the same manner without the loop? I think that you will get a segmentation fault too. Give that a try!

Post the initialization code too.

richmike3 09-11-2009 04:08 AM

Thanks orgcandman,

But, that won't suite best for me. Would you please suggest me more.
Thanks.

-Mr S

richmike3 09-11-2009 04:24 AM

Thanks Johnsfine,

For string array, I can add NULL end, OK. Think about int array. -1 will be a value, I can't add it at end.

Please let me know how can find array is ended.

Thanks

richmike3 09-11-2009 04:28 AM

Hi KarlatLQ,
I can print single string without any error.

Initialization snippet is,

char **strArray;
strArray = (char**) malloc (5 * sizeof(char*));
for (i = 0; i < 5; i++)
{
*strArray = (char*) malloc (5 * sizeof (char));
strArray++;
}

wje_lq 09-11-2009 04:57 AM

Code:

  while (strArray != NULL)      /* wrong */
  while (*strArray != NULL)      /* right */

Also, your initialization snippet does not ensure that the final pointer is followed by a NULL pointer. Try this:
Code:

char **strArray;
strArray = (char**) malloc (6 * sizeof(char*));
for (i = 0; i < 5; i++)
{
*strArray = (char*) malloc (5 * sizeof (char));
strArray++;
}
strArray[5]=NULL;


johnsfine 09-11-2009 08:32 AM

Quote:

Originally Posted by richmike3 (Post 3678426)
For string array, I can add NULL end, OK. Think about int array. -1 will be a value, I can't add it at end.

Please let me know how can find array is ended.

Since no reserved value is available, you need to have the length stored somewhere that can be accessed where needed.

I understand you do not want to pass two variables when passing the array. How about:

to allocate it
Code:

int* my_array = malloc( (desired_size+1)*sizeof(int) );
*(my_array++) = desired size;

to deallocate it
Code:

free(my_array-1);
to use it
Code:

function( int* array ) {
int ndx;
for ( ndx=0; ndx<array[-1]; ++ndx ) {
  do something with array[ndx]
}
}

So except for the allocate/deallocate, everything else can treat it as a nearly ordinary array that happens to have its element count stored at array[-1].

Quote:

Originally Posted by wje_lq (Post 3678468)
Code:

  while (strArray != NULL)      /* wrong */

Very sloppy of me failing to notice that error in the original post. Usually I look more carefully.

karlatLQ 09-11-2009 12:27 PM

Code:

#include <stdio.h>

void main(void)
{
        int i=0;
        char *string[]={"monday","tuesday","wednesday","thursday","friday"};

        for (i=0; i<5; i++)
                printf("%s\n", string[i]);

        return;
}

Try this code. To compile it and to run it:

Code:

> gcc file.c
> /path/to/exe/a.out

You will see that it outputs the five days of the week. Using this type of string array, your program could be made to work right.

richmike3 09-12-2009 11:41 AM

Thank you guys.

I added NULL at end for string array and -1 at the end for int array.

bastl 09-12-2009 06:58 PM

It seems to me that you want to use an array with program arguments argv[].?
An array of arguments is defined like this:
Code:

char *arg[] = {"progname", "op1", (char)0 };
So the end will be detected with:
Code:

while( arg[i] != 0 )
...

So there is no need to search for NULL but for 0 !
And if not, 0 terminated strings are c-strings and will always be handled right by the system !
With NULL there is expressed the need of a char with value 0 and not the character '0' (with value 48).

karlatLQ 09-13-2009 08:40 AM

What compiler are you using?
Could you post the code where you set the string values to the array?

Could you post a test code to print out just one of the arrays in the string?

Quote:

while (strArray != NULL)
{
printf ("%s\n", *strArray);
strArray++;
}
What happened when you tried to run that code? Have you read about pointer arithmetic? I do not think that is what you want to do. Try this piece of code to see what happens:

Code:

printf("\nstrArray = %X", strArray);
strArray++;
printf("\nstrArray = %X", strArray);

What is the program for?

orgcandman 09-14-2009 08:58 AM

Quote:

Originally Posted by bastl (Post 3680495)
It seems to me that you want to use an array with program arguments argv[].?
An array of arguments is defined like this:
Code:

char *arg[] = {"progname", "op1", (char)0 };
So the end will be detected with:
Code:

while( arg[i] != 0 )
...

So there is no need to search for NULL but for 0 !
And if not, 0 terminated strings are c-strings and will always be handled right by the system !
With NULL there is expressed the need of a char with value 0 and not the character '0' (with value 48).

FYI - on intel machines, NULL is 0. On other machines, 0 might be a valid address, so using it as a 'special case' is a bad idea (notably, SV5R4 used 0 as a valid address, and linux can emulate this behavior). It is best practice to check explicitly for NULL, which the C library on your platform 'guarantees' to be correct.

Example:
Quote:

[09:53:11][aconole@weston:~]
$ cat null.c
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
printf("Null [%X]\n", NULL);
return 0;
}
[09:53:16][aconole@weston:~]
$ gcc -o null null.c
[09:53:18][aconole@weston:~]
$ ./null
Null [0]
[09:53:19][aconole@weston:~]
$
As for how arrays are built, you are partly correct for the arguments pointer, but that's because of the exec() specifications. From the manual:
Quote:

The list of arguments must be terminated by a NULL pointer, and, since these are variadic functions, this pointer must be cast (char *) NULL.
-Aaron

bastl 09-14-2009 10:52 AM

Quote:

Originally Posted by orgcandman (Post 3682269)
FYI - on intel machines, NULL is 0. On other machines, 0 might be a valid address, so using it as a 'special case' is a bad idea (notably, SV5R4 used 0 as a valid address, and linux can emulate this behavior).
-Aaron

Sorry, but NULL is never 0x0000:0x0000, this is the address of the first instruction when you turn on or reset your computer and not only Intel. So you would call the first BIOS instruction with NULL - no, NULL is never 0x0000 nor (char) 0, NULL will always be a address different from 0x0000:0x0000 and With c++ you even can't be sure that NULL from a parent is the same NULL of a child. In that case you even can't search for NULL at all. In sure Linux will have an other NULL as you in your program!
And linux system always needs (char) 0 terminated strings like char *st="hallo" is one, and linux needs also the array to be 0 terminated.
NULL only means that it is a pointer to its self and if NULL is used for a call, instead of a function, some POPs and a ret will be added after. So every NULL you use instead of a different function type will be a different NULL !


All times are GMT -5. The time now is 12:27 PM.