Veteran Member
Join Date: Mar 2005
Location: Near Indianapolis
|
I'm working on a project for my intro programming class, and I'm running into a seg-fault at execution time. My deadline is tonight, but I really need to nail down this problem as quickly as possible. Here is My assignment
Right now I'm running into a seg-fault when I try to print my initial configuration. I'll post the relevant code, and if something jumps out at anybody, please let me know! First, my function declaration: Code:
int initconfig(char nT[][WIDTH]); /*Prints initial configuration*/ *Note that WIDTH is a preprocessor constant I've defined as 10. HEIGHT is set to 15.Now my function call from main(): Code:
initconfig(&newTable); And finally, the initconfig function itself:Code:
int initconfig(char nT[][WIDTH]) {
printf("Initial configuration:\n\n");
for (i = 0; i < WIDTH; i++){
for (j = 0; j < HEIGHT; j++) {
printf("%c", &nT[i][j]);
}
}
} *One final note: initconfig is my function to print the first table after the user inputs the beginning coordinates. The newTable array holds the values of the table (a hyphen for unoccupied cells and an asterisk for occupied cells).I've made very little progress here. I'm very much in danger of failing this class, and this project is going to have a huge impact. Help! |
quote |
Veteran Member
Join Date: May 2004
Location: Clayton, NC
|
Quote:
|
|
quote |
Veteran Member
Join Date: Mar 2005
Location: Near Indianapolis
|
Quote:
|
|
quote |
Travels via TARDIS
Join Date: Aug 2005
Location: Earthsea
|
Quote:
Here goes: 1. Personally, I'm flabbergasted that your compiler allows the char nT[][WIDTH] construction. It's not good style. In C, typically all array types must have a fixed size, except for the last set of brackets. Thus, char nT[HEIGHT][] would be OK. But if you know the bounds (both HEIGHT and WIDTH) to start with, why not just define the size of both using char nT[HEIGHT][WIDTH]? 2. Your current declaration is for "an array, nT, of unknown length, in which each item contains a pointer to an array of chars of size WIDTH." I'd be concerned that "newTable" is being constructed incorrectly. A seg fault will happen when you try to access memory that you haven't allocated. With your current delcaration, you'd have to manually allocate HEIGHT rows in nT of type char[WIDTH]. Are you doing this? 3. Using &newTable will cause initconfig() to be passed a pointer to the mess that is your newTable construction, which your current initconfig() doesn't handle. 4. Whoa, you really don't understand pointers, do you? printf("%c", &nT[i][j]) will pass the memory address (& - the "address-of" operator) of nT[i][j] to printf(), not the character at nT[i][j] like you want. For the record, the ampersand (&) operator returns the memory address of a variable, which is usually used to create a pointer to an existing variable. Example: Code:
int myFunction(int *intPointer);
int main(void)
{
int normalInt;
/* Use & to pass myFunction() a pointer to staticInt */
return myFunction(&normalInt);
} 5. Conversely, to dereference a pointer, you do this:Code:
int myFunction(int normalInt);
int main(void)
{
int firstNormalInt;
int *intPointer;
firstNormalInt = 0;
intPointer = &firstNormalInt;
/* Got to dereference the pointer for myFunction() */
/* It's just my style to always keep pointer dereferencing inside */
/* its own set of parenthesis, as to prevent confusion later. */
return myFunction( (*intPointer) );
} My suggestions?Code:
/* Define a type here to make your code more readable. */
typedef char[HEIGHT][WIDTH] StatusTable;
/* Pass initconig() a pointer to an existing StatusTable */
int initconfig(StatusTable *nT)
{
/* ... */
printf("%c", (*nT)[i][j]);
/* ... */
}
/* Just as an example */
int main(void)
{
StatusTable newTable;
newTable[0][0] = 'X'; /* again, an example */
initconfig(&newTable);
} Yeah, your problems sorta stem from terrible mixing of pointers, address-of (ampersand operator), and such. Seg faults almost always stem from trying to access memory you haven't allocated, so when you see a segfault, look for problems with pointers... either accessing memory you haven't allocated (your case, I think), or memory you've already deallocated.I hope some of this makes sense. Sorry, it's a breach of most honor codes for me to help you much more than this; I purposely didn't read your assignment. But it should be fine for me to help you understand the ins-and-outs of the C language Hopefully I've explained how you're incorrectly using array declarations and pointers... maybe? Apparently I call the cops when I see people litter. Last edited by ShadowOfGed : 2005-11-16 at 09:57. Reason: Got my typedef backwards, oopsie. |
|
quote |
Veteran Member
Join Date: Mar 2005
Location: Near Indianapolis
|
Thanks for the suggestions. I'll try to re-work my code as per your suggestions. I'll be back with an update!
|
quote |
Travels via TARDIS
Join Date: Aug 2005
Location: Earthsea
|
Quote:
Apparently I call the cops when I see people litter. |
|
quote |
Veteran Member
Join Date: May 2004
|
See? This is why C is evil for large-scale production code. Pointers, addresses, and arrays all intertwining in this incestuous little ball of crap that produces runtime memory faults.
Evil, I say. (Okay, I like C - but it has its place, and that's at the bottom of a system, yakking with the hardware directly.) |
quote |
Veteran Member
Join Date: Mar 2005
Location: Near Indianapolis
|
Quote:
Now our class message board/e-mail system is down. I can't even communicate with my professor or my lab instructors. Bastard technology Damn, I wish I hadn't forgotten to bring my iPod to campus today... I'm damn bored waiting for them to get the system back up. Hopefully our SSH server doesn't go down too... |
|
quote |
Travels via TARDIS
Join Date: Aug 2005
Location: Earthsea
|
Quote:
</soapbox> :smokey: Yeah yeah, I know that sometimes GC is more efficient because it allocates a pool of memory from the system and then just shifts stuff around inside that, versus allocating/freeing memory all the time. But you could do GC at the kernel level too. "Oh, you want 100 bytes? Well, you've got... 0 right now, so I'll give you 1MB. Then the rest of your allocations will come from that pool until you need more." The only difference is that your pool in C would become fragmented eventually, since it can't rearrange memory locations at that level. But I think most of the efficiency of GC could be matched at the C level, and since you no longer have the overhead of a JVM and all that, it'd probably be comparable. I'm also talking out of my a**, since I'm not yet a kernel-level hacker. Apparently I call the cops when I see people litter. |
|
quote |
Veteran Member
Join Date: May 2004
|
Instead of rehashing it, I'm just going to point to it: http://forums.appleinsider.com/showt...e +collection
Have fun. |
quote |
Banging the Bottom End
Join Date: Jun 2004
|
Quote:
[on topic] I don't think you need the dereference operator (*) in the printf section of this code: Code:
/* Pass initconig() a pointer to an existing StatusTable */
int initconfig(StatusTable *nT)
{
/* ... */
printf("%c", (*nT)[i][j]); // Try printf("%c", nT[i][j]); instead
/* ... */
} |
|
quote |
Veteran Member
Join Date: Mar 2005
Location: Near Indianapolis
|
Quote:
|
|
quote |
Veteran Member
Join Date: Jun 2004
|
I did read the assignment, and it is written precisely so that you wouldn't need to mess with pointers.
What it doesn't expressly say is if you are supposed to wrap around the edges of the table or stop at the edge for the game of life algorithm. I recommend asking about this rather than guessing. Don't put the *'s and _'s that are required as output into the array. The data you have there is actually booleans (1-bit values). Considering the algorithm used, using 0 for unoccupied and 1 for occupied would probably be a good idea, so you can just sum the contents of all appropriate array cells. It's also a good idea to #define those two and use the full name wherever you can. When you are supposed to print the table, just translate the 0's and 1's into hyphens and asterisks in the print function. This shows you treat data and its representation as separate. Also, don't forget to check if the line of input actually is what you expect (two numbers in valid range) before accepting them. If there's a generic way to get bonus points on beginner courses, this is it. ShadowOfGed said everything else that's necessary. |
quote |
Veteran Member
Join Date: Mar 2005
Location: Near Indianapolis
|
Quote:
Quote:
Quote:
Quote:
Quote:
|
|||||
quote |
Travels via TARDIS
Join Date: Aug 2005
Location: Earthsea
|
Quote:
*tosses the can into the recycling bin* Nah, my point was that one of the big arguments I'd heard in favor of Java is not so much the GC (which is nice... sometimes), but the fact that your program has a dedicated heap which means that the JVM doesn't have to spend time in kernel space asking for more memory in 100 byte chunks like you do with a C/C++ program... I was only commenting on the CPU cycle benefits of using a pre-allocated heap versus asking for memory in small chunks as needed. Interesting thread, though. Apparently I call the cops when I see people litter. |
|
quote |
Travels via TARDIS
Join Date: Aug 2005
Location: Earthsea
|
Quote:
So it's perfectly normal to have a rough start with pointers. I'm just farther along and really lucky to somehow "get it," but it makes it tougher for me to try and explain it to others... I'm sure I could have said it better. If I figure out how to word it more clearly, I'll post again. Apparently I call the cops when I see people litter. |
|
quote |
Travels via TARDIS
Join Date: Aug 2005
Location: Earthsea
|
Quote:
Here's a code snippet where your scenario would work, bassplayinMacFiend: Code:
int main(void)
{
StatusTable nT;
nt[0][0] = 'X'; /* whatever, this is just for kicks */
printf("%c", nT[0][0]);
return 0;
} However, since my example has a StatusTable*, the dereferencing is necessary, a la:Code:
int main(void)
{
StatusTable normalTable;
StatusTable *nT;
normalTable[0][0] = 'X';
nT = &normalTable;
printf("%c", (*nT)[0][0]);
return 0;
} Make sense? Mmmkay, good. Note to self: I really hope I'm correct, 'cause I'd rather not eat crow over statements like "Bzzzt! Wrong!", but I don't have a compiler/command line to validate this right now. :smokey: Apparently I call the cops when I see people litter. |
|
quote |
Veteran Member
Join Date: Mar 2005
Location: Near Indianapolis
|
Quote:
|
|
quote |
Veteran Member
Join Date: Jun 2004
|
When you have trouble with pointers, draw a picture of what you think the structure should be. This is the best help when the pointers are part of a larger data structure, and you are constructing it wrong in the code.
The other thing to do is to go step by step through where you pass addresses into functions, any place you manipulate pointers. At any sight of * or &, or start of a function, stop and make sure the type is what you expect. |
quote |
Veteran Member
|
Quote:
|
|
quote |
Veteran Member
Join Date: May 2004
|
Post-Apple ][, my first computer experience of note was building one. Not from a motherboard, CPU, and drive, but from diodes, transistors, and a Motorola 68000 CPU. Had a whopping 1K of RAM, a hexadecimal input keypad, and 8 numeric LED readout. It was required to get a physics degree at UW, because you were expected to know how to build your own custom lab equipment. I had the most fun with that thing - we had to come up with a project to have it interact with the real world, so my lab partner hooked a sonic range finder into it and stored the data in RAM. I then wrote a program to find derivatives across the data, and the distance, velocity, and acceleration could then be displayed on an oscilloscope in X/Y mode.
I <3 (clean) assembly. |
quote |
Veteran Member
|
Quote:
Ahh but my favorite assembler was 6502.. I remember much later when I was working on prototypes 68030 which cost just silly money each (as they weren't mass produced) even then I though assembler was just getting too darn complex! I've never delved into x86 as that was just plain wierd from the first 'till the last time I saw it... Always thought the 680x0 series were more 6502 like.. So I pushed off to program V60s and things like that in Japan... Nothing like shovelling models into a graphics pipeline with a whizzy little processor.. Happy Days! 'Remember, measure life by the moments that take your breath away, not by how many breaths you take' Extreme Sports Cafe | ESC's blog | scratt's blog | @thescratt |
|
quote |
Veteran Member
Join Date: May 2004
|
Wheee! Have you ever taken a gander at the PPC assembly definition? *CLEAN* It managed to maintain the simplicity of something like the 680x0 line while providing much more power. Amazing bit of work.
Ah well, those days are behind us... :} I'm hoping the new GPGP (General Purpose use of Graphical Processors) push will kickstart a new generation of assembly rats. Because it really frightens me when I look at the graduate students we get in CS, and they not only have never played in assembly, or built their own circuitboard, but don't even know how a transistor works. Hell, most of them haven't a clue how a *COMPILER* works. *sigh* Kids these days. |
quote |
Veteran Member
|
*reclines in big red silk armchair*
*puffs on cigar and sips his whiskey* *doffs his hat to Dr. Kick* Absolutely my dear Dr. |
quote |
Posting Rules | Navigation |
|
Thread Tools | |