Discussion:
"PORTING" C > weird char array values displayed in watch window?
(too old to reply)
Robby
2010-01-15 18:22:06 UTC
Permalink
Hello,

Today I ported a small function which values used to display fine in the old
compiler's watch window but now displays weirdly in the watch windows of
MPLAB/C32 and VC++ compilers.

In the last week, I have externed many int variables/arrays and char
variables the way it was instructed to me and up to now they all work fine. I
don't know if this has to do with the fact that externs for *char arrays* are
as valid as for the externs we do for ints and chars.

Basically, I am trying to innitialize a char array with 88 values. They are
simple byte values which have no relation to the ascii charaters. Please view
the small sippet of code:

Please see questions after this code:
=========================main.c
#include <stdio.h>
#include "setup.h"
#include "spi.h" // extern included so to be in scope of this file!

int main()
{
innit_buff();
set_spi_flash_buffer(spiFLASH_BUFFER);
return 0;
}

=======================setup.h
#ifndef SETUP_H
#define SETUP_H

void innit_buff();

#endif // SETUP_H //

=====================setup.c
#include "setup.h"
#include "spi.h"

void innit_buff()
{
int i=0;
// RESET FLASH BUFFER
for(i=0; i<88; i++)
spiFLASH_BUFFER[88] = 97; // <<< buffer assignment!

i = 0; /// BREAKPOINT #1

}

=======================spi.h
#ifndef SPI_H
#define SPI_H

extern unsigned char spiFLASH_BUFFER[88]; // buffer externed in a header
file
void set_spi_flash_buffer(spiFLASH_BUFFER);
#endif // SPI_H //

=======================spi.c
#include "spi.h"

unsigned char spiFLASH_BUFFER[88]; // extern declared in exactly one .c file!

void set_spi_flash_buffer(unsigned char spiFLASH_BUFFER[])
{
int r=0;
for(r=0;r<44;r++)
spiFLASH_BUFFER[r]= 0;

for(r=44;r<88;r++)
spiFLASH_BUFFER[r]= 255;

r=0; // <<< BREAKPOINT #2
}
=================================

QUESTION #1:

When the program hits BREAKPOINT #1, the "buffer assignment" line of code
(in setup.c) assigns to the buffer the value of 97. However, in the watch
window, the values of the "spiFLASH_BUFFER[88]" char array are always "0"
???? and it is displayed in the watch window this way:

spiFLASH_BUFFER 0x00e953c0
[0] ....0
[1] ....0
[2] ....0
[3] ....0
[4] ....0
...
...
[84] ....0
[85] ....0
[86] ....0
[87] ....0

I don't know why they are always 0 as opposed to bieng 97????

QUESTION #2:

When the program hits BREAKPOINT #2, the values of the
"spiFLASH_BUFFER[88]" char array are not even displayed anymore in the watch
window ??? All I see in the watch window now is a small blue cube and 0 as
its value, like this:

spiFLASH_BUFFER 0x00e953c0
[] ....0

I am wondering why I am not seeing every char value in this array this way:

spiFLASH_BUFFER 0x00e953c0
[0] ....0
[1] ....0
[2] ....0
[3] ....0
[4] ....0
...
...
[84] ....255
[85] ....255
[86] ....255
[87] ....255

Even though I am assigning regular numeric values to a char type array, we
should still be able to see them in the watch window... no?

confused!

Can anyone explain to me as to why we are seeing this type of information in
the watch window?

Thankyou all for your help.
--
Best regards
Roberto
Giovanni Dicanio
2010-01-15 18:36:55 UTC
Permalink
Post by Robby
void innit_buff()
{
int i=0;
// RESET FLASH BUFFER
for(i=0; i<88; i++)
spiFLASH_BUFFER[88] = 97; // <<< buffer assignment!
Should it be the following?

spiFLASH_BUFFER[i] = 97;

(instead of spiFLASH_BUFFER[88] = 97, which is also invalid buffer overrun
if spiFLASH_BUFFER has 88 items; in fact, the last item index is N-1 = 88-1
= 87).

Giovanni
Robby
2010-01-15 19:25:02 UTC
Permalink
Hello Giovanni,

Thankfully, this solves question #1.... I thankyou for this. With all the
porting and tests I have been doing I overlooked this.... I appologize.

However, question #2 behaves exactly as I described.... and I don't know why.

Do you see something I don't see?

Thanks!
--
Best regards
Roberto
Post by Giovanni Dicanio
Post by Robby
void innit_buff()
{
int i=0;
// RESET FLASH BUFFER
for(i=0; i<88; i++)
spiFLASH_BUFFER[88] = 97; // <<< buffer assignment!
Should it be the following?
spiFLASH_BUFFER[i] = 97;
(instead of spiFLASH_BUFFER[88] = 97, which is also invalid buffer overrun
if spiFLASH_BUFFER has 88 items; in fact, the last item index is N-1 = 88-1
= 87).
Giovanni
.
Igor Tandetnik
2010-01-15 18:47:53 UTC
Permalink
Robby <***@discussions.microsoft.com> wrote:
t i=0;
Post by Robby
// RESET FLASH BUFFER
for(i=0; i<88; i++)
spiFLASH_BUFFER[88] = 97; // <<< buffer assignment!
You are assigning the same value to the same element spiFLASH_BUFFER[88] mutliple times. Further, 88 is not a valid index into spiFLASH_BUFFER - you have a buffer overrun here. I'm pretty sure you meant spiFLASH_BUFFER[i]
Post by Robby
unsigned char spiFLASH_BUFFER[88]; // extern declared in exactly one .c file!
void set_spi_flash_buffer(unsigned char spiFLASH_BUFFER[])
By giving function parameter the same name as a global variable, you are confusing yourself.
Post by Robby
When the program hits BREAKPOINT #1, the "buffer assignment" line of
code (in setup.c) assigns to the buffer the value of 97.
No it doesn't. It writes the value 97 88 times beyond the end of the buffer. The buffer itself remains unchanged.
Post by Robby
When the program hits BREAKPOINT #2, the values of the
"spiFLASH_BUFFER[88]" char array are not even displayed anymore in
the watch window ??? All I see in the watch window now is a small
spiFLASH_BUFFER 0x00e953c0
[] ....0
Within set_spi_flash_buffer, spiFLASH_BUFFER refers to the function's parameter, not to the global variable. And since the parameter is declared without array size, the debugger doesn't know how many elements you expect it to display.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Robby
2010-01-15 19:59:01 UTC
Permalink
Post by Robby
t i=0;
Post by Robby
// RESET FLASH BUFFER
for(i=0; i<88; i++)
spiFLASH_BUFFER[88] = 97; // <<< buffer assignment!
You are assigning the same value to the same element spiFLASH_BUFFER[88] mutliple times. Further, 88 is not a valid index into spiFLASH_BUFFER - you have a buffer overrun here. I'm pretty sure you meant spiFLASH_BUFFER[i]
Post by Robby
unsigned char spiFLASH_BUFFER[88]; // extern declared in exactly one .c file!
void set_spi_flash_buffer(unsigned char spiFLASH_BUFFER[])
By giving function parameter the same name as a global variable, you are confusing yourself.
Yeah, alot of other things have to still be changed! But yeah, Giovanni
pointed that [88] typo also. I don't know how that got there????
Post by Robby
Post by Robby
When the program hits BREAKPOINT #1, the "buffer assignment" line of
code (in setup.c) assigns to the buffer the value of 97.
No it doesn't. It writes the value 97 88 times beyond the end of the buffer. The buffer itself remains unchanged.
Post by Robby
When the program hits BREAKPOINT #2, the values of the
"spiFLASH_BUFFER[88]" char array are not even displayed anymore in
the watch window ??? All I see in the watch window now is a small
spiFLASH_BUFFER 0x00e953c0
[] ....0
Within set_spi_flash_buffer, spiFLASH_BUFFER refers to the function's parameter, not to the global variable. And since the parameter is declared without array size, the debugger doesn't know how many elements you expect it to display.
ah yes, hum! I don't know why the hell I was passing the array while it was
even declared global *and get this* it always worked in the other bloody old
compiler like as if all of this was normal ...... ooofff! I tel ya! porting
and adjusting to compiler compliance.... this won't be easy!

here's the code that outputs the correct info in the watch window.

=========================main.c
#include <stdio.h>
#include "setup.h"
#include "spi.h"

int main()
{
innit_buff();
set_buffer();
return 0;
}

=====================setup.h
#ifndef SETUP_H
#define SETUP_H

void innit_buff();

#endif // SETUP_H //

=====================setup.c
#include "setup.h"
#include "spi.h"

void innit_buff()
{

int i=0;

// RESET FLASH BUFFERS
for(i=0; i<88; i++)
spiFLASH_BUFFER[i] = 97;

}

=======================spi.h

#ifndef SPI_H
#define SPI_H

extern unsigned char spiFLASH_BUFFER[88];
void set_buffer();

#endif // SPI_H //

=======================spi.c
#include "spi.h"

unsigned char spiFLASH_BUFFER[88];

void set_buffer()
{
int r=0;
for(r=0;r<44;r++)
spiFLASH_BUFFER[r]= 0;

for(r=44;r<87;r++)
spiFLASH_BUFFER[r]= 255;

r = 0;

}
==========================

I made the changes in the real project, and the watch window displays
exactly what I was looking for.

Thankyou Igor.

On another note, Igor, those inclusion guards you showed me 2 weeks ago are
the best thing since sliced bread for me. I include exactly what I need for
every .c file and include within the inclusion guards the .h files that I
need and I don't get confused anymore. Its great!

However, sometimes in header files that others wrote, I sometimes see
multiple inclusion guards in the header files. This obviously tells me that
depending on another defined variable, we would allow different inclusions.
But why would people do this?

regards
Rob
Igor Tandetnik
2010-01-15 21:08:49 UTC
Permalink
Post by Robby
Post by Igor Tandetnik
Within set_spi_flash_buffer, spiFLASH_BUFFER refers to the
function's parameter, not to the global variable. And since the
parameter is declared without array size, the debugger doesn't know
how many elements you expect it to display.
ah yes, hum! I don't know why the hell I was passing the array while
it was even declared global *and get this* it always worked in the
other bloody old compiler like as if all of this was normal ......
It works in VC, too. It is legal to name a parameter, or a local variable, the same as a global variable. It's just confusing - mainly to yourself, because you had this unreasonable expectation that the parameter _is_ the same as the global variable just because it has the same name. Consider:

char x = 'x';
char y = 'y';

void f(char x) {
// x here is unrelated to the global variable named x.
printf("%c\n", x);
}

int main() {
f(y); // prints "y"
return 0;
}
Post by Robby
unsigned char spiFLASH_BUFFER[88];
void set_buffer()
{
int r=0;
for(r=0;r<44;r++)
spiFLASH_BUFFER[r]= 0;
for(r=44;r<87;r++)
spiFLASH_BUFFER[r]= 255;
Did you mean not to assign to spiFLASH_BUFFER[87]?
Post by Robby
However, sometimes in header files that others wrote, I sometimes see
multiple inclusion guards in the header files. This obviously tells
me that depending on another defined variable, we would allow
different inclusions. But why would people do this?
#ifdef et al is not just use for include guards. It's a general purpose mechanism for conditional compilation. Include guards is just one particular application of this general technique:

http://en.wikipedia.org/wiki/C_preprocessor#Conditional_compilation

For example, imagine that you are trying to write code that would compile both on MSVC and on your other compiler where int is 8 bit. Suppose you need an integer type that is always 8 bit regardless of which compiler you are targeting. You can do this:

#if defined (MSVC)
typedef int int8;
#elif defined(MY_OTHER_COMPILER)
typedef signed char int8;
#else
#error Define the compiler you want to build for.
#endif

Now in your project settings (or makefiles, or whatever you use to drive the build) you can define an appropriate macro, and in your code just use int8 knowing that it will be defined appropriately.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Robby
2010-01-16 02:04:03 UTC
Permalink
Post by Igor Tandetnik
It works in VC, too. It is legal to name a parameter, or a local variable,
the same as a global variable. It's just confusing - mainly to yourself,
because you had this unreasonable expectation that the parameter _is_ the
Post by Igor Tandetnik
char x = 'x';
char y = 'y';
void f(char x) {
// x here is unrelated to the global variable named x.
printf("%c\n", x);
}
int main() {
f(y); // prints "y"
return 0;
}
Okay!
Post by Igor Tandetnik
Post by Robby
unsigned char spiFLASH_BUFFER[88];
void set_buffer()
{
int r=0;
for(r=0;r<44;r++)
spiFLASH_BUFFER[r]= 0;
for(r=44;r<87;r++)
spiFLASH_BUFFER[r]= 255;
Did you mean not to assign to spiFLASH_BUFFER[87]?
Come again! I don't understand your question!
Post by Igor Tandetnik
http://en.wikipedia.org/wiki/C_preprocessor#Conditional_compilation
#if defined (MSVC)
typedef int int8;
#elif defined(MY_OTHER_COMPILER)
typedef signed char int8;
#else
#error Define the compiler you want to build for.
#endif
Now in your project settings (or makefiles, or whatever you use to drive the build) you can define an appropriate macro, and in your code just use int8 knowing that it will be defined appropriately.
Understood!

Thanks Igor!
Igor Tandetnik
2010-01-16 02:31:37 UTC
Permalink
Post by Robby
Post by Igor Tandetnik
Post by Robby
unsigned char spiFLASH_BUFFER[88];
void set_buffer()
{
int r=0;
for(r=0;r<44;r++)
spiFLASH_BUFFER[r]= 0;
for(r=44;r<87;r++)
spiFLASH_BUFFER[r]= 255;
Did you mean not to assign to spiFLASH_BUFFER[87]?
Come again! I don't understand your question!
You have declared the array as spiFLASH_BUFFER[88], so valid indexes run from 0 through 87 inclusive. The function above assigns values to elements at indexes 0 through 86, but leaves spiFLASH_BUFFER[87] unchanged. I wondered whether you did it intentionally or accidentally.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Robby
2010-01-16 19:27:01 UTC
Permalink
Post by Igor Tandetnik
You have declared the array as spiFLASH_BUFFER[88], so valid indexes run from 0 through 87 inclusive. The function above assigns values to elements at indexes 0 through 86, but leaves spiFLASH_BUFFER[87] unchanged. I wondered whether you did it intentionally or accidentally.
yes! You are right!

Thanks!

Rob

Loading...