Think I need to update my compiler

I'm using xubuntu and I think I need to update my compiler -- its giving me a weird segmentation fault that I'm fairly certain isn't my fault.

I took code that I formerly had in main and made it into separate functions. My function takes a buffer, and a vector of ints which represents placements in that buffer, and returns an array of strings (names of sports teams) mined from that buffer.

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
string * converttp_to_teams(vector<int> * team_placementsp, char * buffer) {//converts an array of team placements in the buffer to an array of teams, i.e. (Arsenal, ManU, ...) arsenal plays Manu in the first game. 
  int i, j, start=0;
  string * teams_in_order;
  teams_in_order = new string[team_placementsp->size()*2];

  for(i = 0; i< team_placementsp->size(); ++i) {
    start = team_placementsp->at(i);   
  
    for(j = start; buffer[j]!='\"'; --j)
      ; //cycles backwards so we can record the first team first

    for(j+=1; j!=start-2; ++j)
      teams_in_order[2*i]+=buffer[j]; //records up to _v_

    for(j=start+1; buffer[j]!='\"'; ++j) //records from _v_ to "
      teams_in_order[2*i+1]+=buffer[j];
  }

  return teams_in_order;



}

// the function call in main looks like...


string * list_of_teams;

list_of_teams = converttp_to_teams(team_placementsp, buffer); 


The segfault comes at the very first statement, for i =0, start = team_placementsp->at(i) . I've stepped around the program using gdb and team_placementsp is filled with exactly the values I would suppose it is filled with. When I check team_placementsp->at(0) it is as expected, however when we are actually in the function converttp_to_teams, gdb cannot print any of the values in team_placementsp. I get the error...

<error reading variable>

two lines previously, when we're outside the function, gdb has no problem printing any member of the vector team_placementsp. I'm sure its getting passed to the function correctly - I believe this is a problem in the compiler gcc.

Any ideas? How do I update my compiler? (or, alternatively, is there another
Have you allocated a vector object that team_placementsp points to?

Is buffer pointing to a char array? Is it big enough?

In the second loop, are you sure that you find the double quote character? If it's not found j will run into negative values and buffer[j] will probably generate a segfault.

If possible you can try run your program with valgrind. In my experience valgrind is often better than gdb to find these kinds of errors.
Last edited on
Peter -

Yes, I have allocated a vector object that team_placementsp points to. It is modified by a function Find_teamplacements which takes a buffer, a length of that buffer and a vector of ints which it adds elements to until all the team placements in the buffer are found.

There is no problem with buffer, that I am sure. I've had that piece of code implemented for a long time -- simple fstream call that reads a the text file I'm interested in into the buffer array.

Yes, we will find the double quote character. The program worked as I wanted it to, then I partitioned a lot of the work from main() into separate functions, which is where I started running into problems. These are all good suggestions though and easy pitfalls.


Using valgrind was very helpful, thanks for the advice. It appears I was wrong about updating my compiler -- there is some very strange segfaults going on here. Its something to do with the buffer....

Here is the error valgrind is giving me --
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 Invalid read of size 1
==2964==    at 0x8049543: FindString(char const*, std::string, int, int) (data_mine_ctxt.cpp:15)
==2964==    by 0x80495E7: Find_teamplacements(char const*, int, std::vector<int, std::allocator<int> >&) (data_mine_ctxt.cpp:37)
==2964==    by 0x8049C65: main (data_mine_ctxt.cpp:178)
==2964==  Address 0x439b609 is 0 bytes after a block of size 496,673 alloc'd
==2964==    at 0x402B454: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2964==    by 0x8049BFF: main (data_mine_ctxt.cpp:169)
==2964== 
==2964== Invalid read of size 1
==2964==    at 0x8049543: FindString(char const*, std::string, int, int) (data_mine_ctxt.cpp:15)
==2964==    by 0x80497B9: Find_scoreplacements(char const*, int, std::vector<int, std::allocator<int> >&) (data_mine_ctxt.cpp:73)
==2964==    by 0x8049D2D: main (data_mine_ctxt.cpp:191)
==2964==  Address 0x439b609 is 0 bytes after a block of size 496,673 alloc'd
==2964==    at 0x402B454: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2964==    by 0x8049BFF: main (data_mine_ctxt.cpp:169)
==2964== 



What I don't understand is the three functions valgrind references -- FindString, Find_scoreplacements() and Find_teamplacements... don't do anything with dynamic memory, or have pointers and such. Buffer is created and allocated outside of those, in main.

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
 int FindString(const char * haystack, const string needle, int start, int haystacklen) { //returns int  i, where haystack[i] is the last character in needle

      int i, j; 
      j=0;

      for(i=start; i <= haystacklen; ++i) { 

	      if(needle.length() <= j) //we have found the entire needle
		return i-1;// i is the position in the array DIRECTLY AFTER the end of the string. Could cause problems if its the last member in the array!

	      else if(haystack[i] == needle[j]) //we have found part of the needle
		      ++j;

	      else j = 0; //we found part or none of the needle and need to restart
	      }

      return -1; //couldn't find the needle, returns an error 
      

	      }






void Find_teamplacements(const char * buffer, int length, vector<int> & vector_of_teamps){
  int i, j; 
       	    
		for(i=0; 0 <= i; ) {
		j = i;
		
		i = FindString(buffer, "_v_", j, length); // each team is denoted by "_v_", i.e. ManU_v_Arsenal

		if( i!=-1)
		vector_of_teamps.push_back (i);
		
		}

		
}

void Find_scoreplacements(const char * buffer, int length, vector<int> & vector_of_scoreps){
  int i, j;


	    for(i = 0; 0<=i;  ){
		      j = i;
		      i = FindString(buffer, "<th align=\"center\" valign=\"top\" width=\"13%\">", j, length);// is the error because i'm double passing buffer? 
		      
		      if(i!=-1)
		      vector_of_scoreps.push_back(i);
		    }
  

}


here is their call in main, along with how buffer is allocated:

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
int main() {

      int i, j;
      char * buffer;


      ifstream file; 
      int length;
      file.open("2009_10_UEFA_Champions_League_group_stage.txt");

      file.seekg(0, ios::end); 
		      length = file.tellg(); 
		      file.seekg(0, ios::beg);

		      //allocate memory

		      buffer = new char[length];

		      //read data as a block:
		      file.read(buffer,length);
		      file.close();
		      

   vector<int>  vector_of_teamps; 
       Find_teamplacements(buffer, length, vector_of_teamps);

  vector<int>  vector_of_scoreps;
       Find_scoreplacements(buffer, length, vector_of_scoreps);

}


thanks for any help!
I guess the "invalid read of size 1" on line 15 in data_mine_ctxt.cpp is this line

else if(haystack[i] == needle[j]) //we have found part of the needle

This happens when i == haystacklen, so the real problem is this line

for(i=start; i <= haystacklen; ++i) {

<= should be <.
Last edited on
g++ amazing compiler
Topic archived. No new replies allowed.