C++ - dynamically allocating memory to array of structs

  • Context: C/C++ 
  • Thread starter Thread starter mattskie
  • Start date Start date
  • Tags Tags
    Array C++ Memory
Click For Summary

Discussion Overview

The discussion revolves around dynamically allocating memory for an array of structs in C++, specifically focusing on a struct representing a playing card. Participants explore issues related to memory allocation, segmentation faults, and reading data from a file into the struct's members, while adhering to specific constraints imposed by a project requirement.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Mathematical reasoning
  • Experimental/applied

Main Points Raised

  • One participant describes the constraints of their project, which prohibits the use of std::string, classes, and constructors, requiring the use of C-style strings and dynamic memory allocation outside the struct.
  • Another participant points out a potential source of segmentation faults related to accessing an out-of-bounds index in the array of structs.
  • A participant mentions that their code reads incorrect values ("suit rank 0") instead of the expected card values, indicating a problem in the loop that copies data from the file.
  • There is a suggestion to use debugging techniques, such as adding print statements or breakpoints, to identify where the code fails to read the correct values from the input file.
  • Some participants discuss the validity of accessing one past the end of an array, with differing interpretations of the C++ standard regarding this practice.
  • Another participant questions whether obtaining the address of an out-of-bounds element counts as accessing it, suggesting a misunderstanding of memory access rules.

Areas of Agreement / Disagreement

Participants express differing views on the validity of accessing one past the end of an array, and there is no consensus on the best approach to resolve the segmentation fault or the data reading issue. The discussion remains unresolved regarding the exact cause of the incorrect values being read.

Contextual Notes

Participants note limitations in their code related to memory allocation and file reading, but do not resolve the underlying issues. There are also references to the C++ standard's clarity on array access, which remains a point of contention.

mattskie
Messages
10
Reaction score
0
Let me start by saying I know this is a funky way to program, but my teacher is requiring us to go about it this way.

also:
I CANT use std::string, classes, constructors for this project.
I am required to use this archaic method of c-style strings with dynamic memory allocation occurring outside the struct.. i know its not the best way to go about this, but there's nothign i can go. :(

I have a struct
struct card
{
char *suit;
char *rank;
int cvalue;
}

I've created a pointer of size 52 for my deck

card *deckPtr = new card[52];
card *deckHome = &deckPtr[0];
I then try to use

for(int i=0;i<52;i++)
{
(*deckPtr).suit = new char[8];
(*deckPtr).rank = new char[7];
deckPtr++
}
deckPtr=deckHome;

I am essentially trying to fill in these arrays from a card file, but I cannot make it past running the program, i get sa seg fault which I don't understand why.

I dynamically allocate memory in my card read in function..
void cardInit(card *deckPtr)
{
card *deckHome = &deckPointer[0];
ifstream fin;
char *finName = new char[13];
cin >> *finName
fin.open(finName)
.
.
.
while(fin.good())
{
for(deckPointer=&deckHome[0];deckPointer<&deckHome[52];deckPointer++)
{
fin >> (*deckPointer).suit;
fin >> (*deckPointer).rank;
fin >> (*deckPointer).cvalue;
}
}
Its a pretty simple program..and my dynamic memory works for the file name, but I can't figure out why it doesn't work for structs?
 
Technology news on Phys.org
mattskie said:
Let me start by saying I know this is a funky way to program, but my teacher is requiring us to go about it this way.

also:
I CANT use std::string, classes, constructors for this project.
I am required to use this archaic method of c-style strings with dynamic memory allocation occurring outside the struct.. i know its not the best way to go about this, but there's nothign i can go. :(

I have a struct
struct card
{
char *suit;
char *rank;
int cvalue;
}

I've created a pointer of size 52 for my deck

card *deckPtr = new card[52];
card *deckHome = &deckPtr[0];
I then try to use

for(int i=0;i<52;i++)
{
(*deckPtr).suit = new char[8];
(*deckPtr).rank = new char[7];
deckPtr++
}
deckPtr=deckHome;

I am essentially trying to fill in these arrays from a card file, but I cannot make it past running the program, i get sa seg fault which I don't understand why.

I dynamically allocate memory in my card read in function..
void cardInit(card *deckPtr)
{
card *deckHome = &deckPointer[0];
ifstream fin;
char *finName = new char[13];
cin >> *finName
fin.open(finName)
.
.
.
while(fin.good())
{
for(deckPointer=&deckHome[0];deckPointer<&deckHome[52];deckPointer++)
{
fin >> (*deckPointer).suit;
fin >> (*deckPointer).rank;
fin >> (*deckPointer).cvalue;
}
}
Its a pretty simple program..and my dynamic memory works for the file name, but I can't figure out why it doesn't work for structs?
After a cursory look at your code, I believe this line might be the source of your problem:
Code:
for(deckPointer=&deckHome[0];deckPointer<&deckHome[52];deckPointer++)
deckHome[52] is outside the array, so you shouldn't be trying to access it. The valid indexes for your array are 0 through 51.

When you get the seg fault, is there a line number for the code where the fault occurs? Since this is a run-time error, probably not.

If you're using a debugger, it should be fairly easy to spot where the error occurs. (You should be using a debugger...)

As an alternative, put a print statement inside that loop that displays a count of the number of times the loop has run. If you get no output, then what I said above is very likely the problem.
 
Code:
#include <iostream>
#include <fstream>
#include <ctime>
#include <stdlib.h>
#include <string>

using namespace std;

//global constant(s)
const int maxCards = 52;

//Structs
struct card
  {
  char *suit;
  char *rank;
  int cvalue;
  char location;
  };

//Function List
void readPlayers(player *peoplePointer);
void shuffleCards(card *unshuffled, card* shuffled);

//program
int main()
{//create pointer and set initial value
card * deckPointer = new card[52];
card *deckHome = &deckPointer[0];
for(int i=0;i<maxCards;i++)
{
(*deckPointer).suit=new char[8];
(*deckPointer).rank = new char[7];
deckPointer++;
}
deckPointer = deckHome;
cardInit(deckPointer);
readDeck(deckPointer);//sets default values for the card arrays
for(int i=0;i<52;i++)
  {
 
  strcopy((*deckPointer).suit,"suit");
  strcopy((*deckPointer).rank,"rank");
  (*deckPointer).cvalue = 0;
  deckPointer++;
  }
deckPointer = deckHome;
return 0;
}

//Functions

void cardInit(card *deckPointer)
{
card * deckHome = NULL;
deckHome = &deckPointer[0];
//set up card file to be read in
ifstream fin;
char *finName = new char[13];

//get file name from user
cout << "Enter file name...(cardFile.txt)" << endl;;
cin >> *finName;//open the file
fin.open(finName);//check if cardFile.txt opens correctly
if(!fin.good())
  {
  cout << "Error with card file" << endl;

  }
else
  {
  deckPointer = deckHome;
  while(fin.good())
  {
    for(int i=0;i<50;i++)
  {
  fin >> (*deckPointer).suit;
  fin >> (*deckPointer).rank;
  fin >> (*deckPointer).cvalue;
  deckPointer++;

  }
  }
  }
delete [] finName;
}
 
Did that work? Or at least work better?

I added [ code ] and [ /code ] tags around your code. We encourage people to use them to preserve any indentation they're using, which makes the code easier to read.
 
my code only reads the "suit rank 0" 52 times instead of the correct "heart two 2" up to "spade ace 11"..

so my code no longer seg faults, but something is wrong in my loop that copies the card..do you happen to have any insight to the problem?
 
Code:
for(int i=0;i<52;i++)
{
  strcopy((*deckPointer).suit,"suit");
  strcopy((*deckPointer).rank,"rank");
  (*deckPointer).cvalue = 0;
  deckPointer++;
}
I don't believe your code is reading "suit rank 0" 52 times. The loop above sets each member of your struct array to these values. If you're ending up with all members still set to the values as above, it looks like your code to read from the text file isn't working. When you get your code working, you can delete the loop above.

If you're using a debugger, set a breakpoint in this loop (where you're reading from the input file) or add the line that I show with the comment:
Code:
for(int i=0;i<50;i++)
{
  printf("i is %d\n", i);  // Added line
  fin >> (*deckPointer).suit;
  fin >> (*deckPointer).rank;
  fin >> (*deckPointer).cvalue;
  deckPointer++;
}
The purpose of this is to see if suit, rank, and cvalue are getting set to the values in the input file.
 
Thanks Mark! I figured out my issue!
 
Mark44 said:
After a cursory look at your code, I believe this line might be the source of your problem:
Code:
for(deckPointer=&deckHome[0];deckPointer<&deckHome[52];deckPointer++)
deckHome[52] is outside the array, so you shouldn't be trying to access it. The valid indexes for your array are 0 through 51.
His usage if fine. The 2003 version of the standard is not quite clear as it should be on whether these "one past the end" constructs are valid. It is very clear that deckPointer<deckHome+52 is without a doubt valid. Whether or not &deckHome[52] is valid depends on how nit-picky of a language lawyer one is. (Compare with the C99 standard, which explicitly makes it clear that both deckHome+52 and &deckHome[52] are valid.) The C++11 standard clarifies this: &deckHome[52] is valid.

That said, whether a compiler is compliant with the standard is a different issue.
 
Looks like I am missing something. Does &deckHome[52] count as accessing the element? Isn't it just asking for the address (in which case it shouldn't matter whether the object exists, as long as we don't try to use the address to access memory)?
 
  • #10
Borek said:
Looks like I am missing something. Does &deckHome[52] count as accessing the element? Isn't it just asking for the address (in which case it shouldn't matter whether the object exists, as long as we don't try to use the address to access memory)?
The problem is the goofy way operator[] is defined in C and for primitive arrays in C++. The expression some_array[42] has always been defined as meaning *(some_array+42). One wonderful side effect of this definition is that the expression 42[some_array] is perfectly valid and means exactly the same thing as some_array[42]. Another wonderful side effect: &deckHome[52] means &*(deckHome+52). So is that "&*" a no-op, or does it mean something special?
 
  • #11
Borek said:
Looks like I am missing something. Does &deckHome[52] count as accessing the element?

In C++, it might. If decHome is an object that declares operator[], the latter (ignoring the effects of optimization) will have to be called.

D H said:
The C++11 standard clarifies this: &deckHome[52] is valid.

I have been unable to find this clarification. Could you indicate which section of the std does that?
 

Similar threads

  • · Replies 17 ·
Replies
17
Views
3K
  • · Replies 12 ·
Replies
12
Views
3K
Replies
89
Views
7K
  • · Replies 6 ·
Replies
6
Views
3K
  • · Replies 23 ·
Replies
23
Views
2K
  • · Replies 19 ·
Replies
19
Views
3K
  • · Replies 4 ·
Replies
4
Views
3K
  • · Replies 8 ·
Replies
8
Views
5K
  • · Replies 118 ·
4
Replies
118
Views
10K
  • · Replies 3 ·
Replies
3
Views
2K