Problem with pointers, VS says int is null?

I am writing a sale compiler for a garage sale my debate team is managing, this is the secondary compiler to the main class and it is giving me a runtime error. The visual studio code anyalsis says

1
2
3
4
5
6
7
8
C6385	Read overrun	Reading invalid data from 'files[l].list':  the readable size is '((unsigned int)=len*1)*80+4' bytes, but '160' bytes may be read.	Sales Compiler	salecompiler.cpp	23
'l' is NULL			17
Enter this loop, (assume 'l<len')			17
'l' is an Output from 'std::basic_string<char,std::char_traits<char>,std::allocator<char> >::=' (declared at c:\program files (x86)\microsoft visual studio 11.0\vc\include\xstring:969)			19
Enter this loop, (assume 'i<temp[l].length')			21
'i' may equal 1			21
Continue this loop, (assume 'i<temp[l].length')			21
Invalid read from 'files[l].list[1]', (readable range is 0 to 0)			23


Here is the code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SaleCompiler::SaleCompiler(SaleList * temp, int len )
{
	final = NULL;
	files = new SaleList[len];
	int l = 0;
	for(l = 0;l<len;l++)
	{
		files[l].fileName = temp[l].fileName;
		files->list = new Sale[len];
		for(int i = 0;i<temp[l].length;i++)
		{
			files[l].list[i].setHour(temp[l].list[i].getHour());
			files[l].list[i].setMin(temp[l].list[i].getMin());
			files[l].list[i].setSec(temp[l].list[i].getSec());
			files[l].list[i].setName(temp[l].list[i].getName());
			files[l].list[i].setTime(temp[l].list[i].getTime());
			files[l].list[i].setPrice(temp[l].list[i].getPrice());
		}
		files[l].length = temp[l].length;
	}
	length = len;
}


Objects with pointers use the -> operator to access public methods instead of the . operator. So, any time you need to access the temp variable, you'll have to use it like this:

1
2
3
files[l].fileName = temp[l]->fileName;
//...
files[l].length = temp[l]->length;


You also might want to make sure that the files variable is a pointer-type too, otherwise, you can't allocate space on the heap for a new SaleList object.

1
2
3
// Lines 3 and 4
int final = NULL;
SaleList* final = new SaleList[len];


Hope this helps.
Last edited on
I changed it to
1
2
3
4
5
6
7
8
9
10
11
12
files[l].fileName = temp[l]->fileName;
		files->list = new Sale[len];
		for(int i = 0;i<temp[l];i<length;i++)
		{
			files[l].list[i].setHour(temp[l].list[i].getHour());
			files[l].list[i].setMin(temp[l].list[i].getMin());
			files[l].list[i].setSec(temp[l].list[i].getSec());
			files[l].list[i].setName(temp[l].list[i].getName());
			files[l].list[i].setTime(temp[l].list[i].getTime());
			files[l].list[i].setPrice(temp[l].list[i].getPrice());
		}
		files[l-1].length = temp[l-1]->length;

but it wont compile it says that expression(temp[l]->fileName;temp[l]->length)
must have a pointer type.
Files is a pointer
SaleList * files;

Sale*final;
here is the header file if it will help
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#pragma once
#include "Sale.h"
#include "SaleList.h"
class SaleCompiler
{
public:
	SaleCompiler(void);
	SaleCompiler::SaleCompiler(SaleList * temp, int len);
	~SaleCompiler(void);
	void getFinal(Sale *temp);
	void sortFinal();
	void mergeFiles();
	int getTotalSize()
	{
		return totalSize;
	}
protected:
	SaleList * files;
	Sale * final;
	int totalSize;
	int length;
};
Last edited on
You are stepping out of bounds of your array and accessing array elements that don't exist.

This block of code has several problems. Note my comments:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SaleCompiler::SaleCompiler(SaleList * temp, int len )
{
	final = NULL;
	files = new SaleList[len];  // allocating 'len' elements for 'files'.  This is good.
	int l = 0;
	for(l = 0;l<len;l++)  // using 'l' to index 'files'.  As long as 'l' is less than 'len', this is good.
	{
		files[l].fileName = temp[l].fileName;
		files->list = new Sale[len];  // PROBLEM: you are doing files->list which is the same as files[0].list, which probably isn't what you wanted.
		// also you are allocating 'len' elements and not 'temp[l].length' elements like you probably wanted
		for(int i = 0;i<temp[l].length;i++)
		{
			files[l].list[i].setHour(temp[l].list[i].getHour()); // PROBLEM surfaces again here.  You are using 'l' to index temp and files, which is fine, but you are using 'i' to index list, which is wrong.
// what if 'i' is greater than len?  If that happens: EXPLODE
//  also, because you never set files[l].list to anything, it's probably a bad pointer (see files->list problem above) 



Another problem is you are doing all these new[]s but never any delete[]s, which means you are leaking memory. Every new[] must have a matching delete[].

The easiest way to manage that is to simply don't use new if you can avoid it.

Here, you could do this with a vector instead.

Futhermore... if you're using vectors, you don't have to worry about managing memory or even copying objects like this. You can just copy the vectors in full.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#pragma once
#include "Sale.h"
#include "SaleList.h"
#include <vector>  // use vectors!
class SaleCompiler
{
public:
	SaleCompiler(); // <- not important... but get rid of that (void) business.  That's C garbage.
	SaleCompiler::SaleCompiler(const std::vector<SaleList>& temp); // <-take a vector instead of a pointer+length
	~SaleCompiler();  // <- getting rid of (void) garbage here too
	void getFinal(Sale *temp);
	void sortFinal();
	void mergeFiles();
	int getTotalSize()
	{
		return totalSize;  // <- I'm not sure what to change this to.  Either files.size() or final.size(), whichever size you intended here
	}
protected:
/*	SaleList * files;  get rid of all this crap
	Sale * final;
	int totalSize;
	int length;
*/
	// replace it with vectors:
	std::vector<SaleList> files;
	std::vector<Sale> final;
};


/*

Now your big complicated constructor:

SaleCompiler::SaleCompiler(SaleList * temp, int len )
{
	final = NULL;
	files = new SaleList[len];
	int l = 0;
	for(l = 0;l<len;l++)
	{
		files[l].fileName = temp[l].fileName;
		files->list = new Sale[len];
		for(int i = 0;i<temp[l].length;i++)
		{
			files[l].list[i].setHour(temp[l].list[i].getHour());
			files[l].list[i].setMin(temp[l].list[i].getMin());
			files[l].list[i].setSec(temp[l].list[i].getSec());
			files[l].list[i].setName(temp[l].list[i].getName());
			files[l].list[i].setTime(temp[l].list[i].getTime());
			files[l].list[i].setPrice(temp[l].list[i].getPrice());
		}
		files[l].length = temp[l].length;
	}
	length = len;
}

... can be greatly simplified:

*/

SaleCompiler::SaleCompiler(const std::vector<SaleList>& temp )
    : files(temp)  // done!
{
    // files = temp;  // <- this would have the same effect, more or less, and would also work
    //   but is less optimal that using files' constructor as illustrated above.
}




EDIT:

In case you are unfamiliar with vectors, they're basically resizable arrays:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
vector<int> foo(10);  // an array of 10 ints

// can treat it just like an array:
foo[0] = 5;
foo[1] = foo[0] + 2;

// but you can also resize it:
foo.resize(50);  // now it has 50 ints instead of just 10.

// and you can also append things to the end easily:
foo.push_back(5);  // pushes '5' onto the end of the array.  Array now has 51 elements.

// and they're also copyable:
vector<int> bar;  // another array

bar = foo;  // now the 'bar' array is a copy of the 'foo' array. 
Last edited on
Thank you so much Disch, I was compeletely stumped. I should really read into vectors considering you just simplified my constructor to one line
Topic archived. No new replies allowed.