Function pointer suddenly causes segmentation fault

Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved

Join Date: Jul 2008
Posts: 49
Reputation: OffbeatPatriot is an unknown quantity at this point 
Solved Threads: 0
OffbeatPatriot OffbeatPatriot is offline Offline
Light Poster

Function pointer suddenly causes segmentation fault

 
0
  #1
Jul 9th, 2009
Basically I'm trying to run a simulation of neurons and this is the code that gets run in the main loop of it.

  1. class Neuron
  2. {
  3. private:
  4. double v, u, a, b, c, d, current, du, dv;
  5. public:
  6. double x;
  7. vector<double> pre;
  8. int id;
  9. vector<int> fired;
  10. vector<int*> post;
  11. vector<double (*)(double)> injections;
  12. vector<double> spikes;
  13. Neuron(Cluster *cluster, int id)
  14. {
  15. v = -55;
  16. u = 0;
  17. this->id = id;
  18. x = uniform();
  19. a = cluster->a();
  20. b = cluster->b();
  21. c = cluster->c();
  22. d = cluster->d();
  23. }
  24. void integrate(double time)
  25. {
  26. current = 0;
  27. for(unsigned int i = 0;i < injections.size();i++)
  28. {
  29. current += injections[i](time);//program crashes here!!!
  30. }
  31. du = a*(b*v - u);
  32. v += .5*(0.04*pow(v, 2) + 5*v + 140 - u + current);
  33. v += .5*(0.04*pow(v, 2) + 5*v + 140 - u + current);
  34. u += du;
  35. if(v >= 30)
  36. {
  37. v = c;
  38. u += d;
  39. for(unsigned int q = 0;q < post.size();q++)
  40. {
  41. *post[q] = 1;
  42. }
  43. spikes.push_back(time);
  44. }
  45. }
  46. void sum()
  47. {
  48. for(unsigned int q = 0;q < pre.size();q++)
  49. {
  50.  
  51. if(fired[q])
  52. {
  53. v += pre[q];
  54. fired[q] = 0;
  55. }
  56.  
  57. }
  58. }
  59. };
  60.  
  61. boost::barrier *neural_sync;
  62.  
  63. void main_loop(vector<Neuron*> neurons, double time_limit, double resolution)
  64. {
  65. for(double t = 0;t < time_limit;t += resolution)
  66. {
  67. printf("simulating %f\n", t);
  68. for(unsigned int i = 0;i < neurons.size();i++)
  69. {
  70. neurons[i]->integrate(t);
  71. }
  72. neural_sync->wait();
  73. for(unsigned int i = 0;i < neurons.size();i++)
  74. {
  75. neurons[i]->sum();
  76. }
  77. neural_sync->wait();
  78. }
  79. }

I'll put the full code at the end of the post if you need to see it and/or run it yourself, you'll need boost threads to build it. The program runs fine for a while and then a segmentation fault occurs at the line I point out above(line 29). The program runs that line several thousand times just fine before the fault occurs.

What I find really perplexing is that if I change

current += injections[i](time);

to

injections[i](time);

it runs fine.

Also the pointers in the injections vector point to one of two functions.

  1. boost::mt19937 range;
  2. boost::normal_distribution<> values_normal(0, 1);
  3. boost::variate_generator<boost::mt19937&, boost::normal_distribution<> > normal(range, values_normal);
  4.  
  5. double e_i(double a)
  6. {
  7. return 5*normal();
  8. }
  9.  
  10. double i_i(double a)
  11. {
  12. return 2*normal();
  13. }

If I alter those functions so they return smaller numbers the program ones fine.

source code:

I ran this with g++ with "g++ -o main main.cpp -lboost_thread"

main.cpp
  1. #include <stdio.h>
  2. #include "Brain.h"
  3. #include <stdlib.h>
  4. #include <time.h>
  5.  
  6. ////////////////////////////////////////////////////////////////
  7. double e_a()
  8. {
  9. return .02;
  10. }
  11.  
  12. double e_b()
  13. {
  14. return .2;
  15. }
  16.  
  17. double e_c()
  18. {
  19. return -65 + 15*pow(uniform(), 2);
  20. }
  21.  
  22. double e_d()
  23. {
  24. return 8 - 6*pow(uniform(), 2);
  25. }
  26.  
  27. double e_s()
  28. {
  29. return .5*uniform();
  30. }
  31.  
  32. double e_i(double a)
  33. {
  34. return 5*normal();
  35. }
  36. ///////////////////////////////////////////////////////////
  37. double i_a()
  38. {
  39. return .02 + .08*uniform();
  40. }
  41.  
  42. double i_b()
  43. {
  44. return .25 - .05*uniform();
  45. }
  46.  
  47. double i_c()
  48. {
  49. return -65;
  50. }
  51.  
  52. double i_d()
  53. {
  54. return 2;
  55. }
  56.  
  57. double i_s()
  58. {
  59. return -rand()/(double)RAND_MAX;
  60. }
  61.  
  62. double i_i(double a)
  63. {
  64. return 2*normal();
  65. }
  66.  
  67. int main()
  68. {
  69. time_t seconds;
  70. time(&seconds);
  71. range.seed((unsigned int) seconds);
  72.  
  73. vector<Cluster*> clusters;
  74.  
  75. clusters.push_back(new Cluster(800, &e_a, &e_b, &e_c, &e_d));
  76. clusters.push_back(new Cluster(200, &i_a, &i_b, &i_c, &i_d));
  77.  
  78. clusters[0]->connect(clusters[0], &e_s);
  79. clusters[0]->connect(clusters[1], &e_s);
  80. clusters[1]->connect(clusters[0], &i_s);
  81. clusters[1]->connect(clusters[1], &i_s);
  82.  
  83. clusters[0]->inject(&e_i);
  84. clusters[1]->inject(&i_i);
  85.  
  86. simulate(clusters, 1000, 1, 1);
  87.  
  88. return 0;
  89. }

Brain.h
  1. #ifndef NEURON_GROUP_H_INCLUDED
  2. #define NEURON_GROUP_H_INCLUDED
  3.  
  4. #include <vector>
  5. #include <map>
  6. #include <math.h>
  7. #include <fstream>
  8.  
  9. #include <boost/thread/thread.hpp>
  10. #include <boost/thread/barrier.hpp>
  11. #include <boost/shared_array.hpp>
  12. #include <boost/random.hpp>
  13. #include <boost/bind.hpp>
  14.  
  15. using namespace std;
  16.  
  17. boost::mt19937 range;
  18.  
  19. boost::uniform_real<> values(0, 1);
  20. boost::variate_generator<boost::mt19937&, boost::uniform_real<> > uniform(range, values);
  21.  
  22. boost::normal_distribution<> values_normal(0, 1);
  23. boost::variate_generator<boost::mt19937&, boost::normal_distribution<> > normal(range, values_normal);
  24.  
  25. class Cluster;
  26. class Neuron;
  27.  
  28. boost::mutex m_mutex;
  29.  
  30. class Connection
  31. {
  32. public:
  33. Cluster *target;
  34. double density, size;
  35. double (*weights)();
  36. Connection(Cluster *target, double (*weights)(), double density, double size)
  37. {
  38. this->target = target;
  39. this->weights = weights;
  40. this->density = density;
  41. this->size = size;
  42. }
  43. };
  44.  
  45. class Injection
  46. {
  47. public:
  48. double density, size;
  49. double (*source)(double);
  50. Injection(double (*source)(double), double density, double size)
  51. {
  52. this->source = source;
  53. this->density = density;
  54. this->size = size;
  55. }
  56. };
  57.  
  58. class Cluster
  59. {
  60. public:
  61. vector<Neuron*> neurons;
  62. vector<Connection*> connections;
  63. vector<Injection*> injections;
  64. int neuron_num, connection_num, injection_num;
  65. double (*a)(), (*b)(), (*c)(), (*d)();
  66. Cluster(int neuron_num, double (*a)(),double (*b)(),double (*c)(),double (*d)())
  67. {
  68. this->neuron_num = neuron_num;
  69. this->a = a;
  70. this->b = b;
  71. this->c = c;
  72. this->d = d;
  73. }
  74. void connect(Cluster *target, double (*weights)(), double density = 1, double size = 1)
  75. {
  76. connections.push_back(new Connection(target, weights, density, size));
  77. }
  78. void inject(double (*source)(double), double density = 1, double size = 1)
  79. {
  80. injections.push_back(new Injection(source, density, size));
  81. }
  82. };
  83.  
  84. class Neuron
  85. {
  86. private:
  87. double v, u, a, b, c, d, current, du, dv;
  88. public:
  89. double x;
  90. vector<double> pre;
  91. int id;
  92. vector<int> fired;
  93. vector<int*> post;
  94. vector<double (*)(double)> injections;
  95. vector<double> spikes;
  96. Neuron(Cluster *cluster, int id)
  97. {
  98. v = -55;
  99. u = 0;
  100. this->id = id;
  101. x = uniform();
  102. a = cluster->a();
  103. b = cluster->b();
  104. c = cluster->c();
  105. d = cluster->d();
  106. }
  107. void integrate(double time)
  108. {
  109. current = 0;
  110. for(unsigned int i = 0;i < injections.size();i++)
  111. {
  112. current += injections[i](time);
  113. }
  114. du = a*(b*v - u);
  115. v += .5*(0.04*pow(v, 2) + 5*v + 140 - u + current);
  116. v += .5*(0.04*pow(v, 2) + 5*v + 140 - u + current);
  117. u += du;
  118. if(v >= 30)
  119. {
  120. v = c;
  121. u += d;
  122. for(unsigned int q = 0;q < post.size();q++)
  123. {
  124. *post[q] = 1;
  125. }
  126. spikes.push_back(time);
  127. }
  128. }
  129. void sum()
  130. {
  131. for(unsigned int q = 0;q < pre.size();q++)
  132. {
  133. if(fired[q])
  134. {
  135. v += pre[q];
  136. fired[q] = 0;
  137. }
  138.  
  139. }
  140. }
  141. };
  142.  
  143. boost::barrier *neural_sync;
  144.  
  145. void main_loop(vector<Neuron*> neurons, double time_limit, double resolution)
  146. {
  147. for(double t = 0;t < time_limit;t += resolution)
  148. {
  149. printf("simulating %f\n", t);
  150. for(unsigned int i = 0;i < neurons.size();i++)
  151. {
  152. neurons[i]->integrate(t);
  153. }
  154. neural_sync->wait();
  155. for(unsigned int i = 0;i < neurons.size();i++)
  156. {
  157. neurons[i]->sum();
  158. }
  159. neural_sync->wait();
  160. }
  161. }
  162.  
  163. void simulate(vector<Cluster*> brain, double time_limit, double resolution = 1, int thread_num = 1)
  164. {
  165. vector<vector<Neuron*> > thread_neurons(thread_num);
  166.  
  167. Cluster *tmp;
  168. unsigned int thread = 0;
  169. int id = 0, total_neurons = 0;
  170. bool cull_threads = true;
  171. Neuron *neuron;
  172. for(unsigned int i = 0;i < brain.size();i++)
  173. {
  174. tmp = brain[i];
  175. total_neurons += tmp->neuron_num;
  176. for(int u = 0;u < tmp->neuron_num;u++)
  177. {
  178. neuron = new Neuron(tmp, id++);
  179. tmp->neurons.push_back(neuron);
  180.  
  181. thread_neurons[thread].push_back(neuron);
  182. thread = (thread + 1) % thread_num;
  183. if(thread == 0)
  184. cull_threads = false;
  185. }
  186. }
  187.  
  188. if(cull_threads)
  189. {
  190. thread_num = thread;
  191. thread_neurons.resize(thread_num);
  192. }
  193. printf("building neurons\n");
  194. double target_x;
  195. Neuron *from_neuron, *to_neuron;
  196. for(unsigned int i = 0;i < brain.size();i++)
  197. {
  198. tmp = brain[i];
  199. for(unsigned int u = 0;u < tmp->neurons.size();u++)
  200. {
  201. from_neuron = tmp->neurons[u];
  202. for(unsigned int q = 0;q < tmp->connections.size();q++)
  203. {
  204. target_x = uniform();
  205. for(unsigned int p = 0;p < tmp->connections[q]->target->neurons.size();p++)
  206. {
  207. to_neuron = tmp->connections[q]->target->neurons[p];
  208. if(from_neuron != to_neuron && abs(target_x - to_neuron->x) <= tmp->connections[q]->size && uniform() < tmp->connections[q]->density)
  209. {
  210. to_neuron->pre.push_back(tmp->connections[q]->weights());
  211.  
  212. to_neuron->fired.push_back(0);
  213.  
  214. from_neuron->post.push_back(&to_neuron->fired[to_neuron->fired.size() - 1]);
  215. }
  216. }
  217. }
  218. for(unsigned int q = 0;q < tmp->injections.size();q++)
  219. {
  220. target_x = uniform();
  221. if(abs(target_x - from_neuron->x) <= tmp->injections[q]->size && uniform() < tmp->injections[q]->density)
  222. {
  223. from_neuron->injections.push_back(tmp->injections[q]->source);
  224. }
  225. }
  226. }
  227. }
  228.  
  229. neural_sync = new boost::barrier(thread_num);
  230.  
  231. printf("starting simulation\n");
  232.  
  233. boost::shared_array<boost::thread> threads = boost::shared_array<boost::thread>(new boost::thread[thread_num]);
  234. for(int i = 0;i < thread_num;i++)
  235. {
  236. threads[i] = boost::thread(boost::bind(&main_loop, thread_neurons[i], time_limit, resolution));
  237. }
  238.  
  239. for(int i = 0;i < thread_num;i++)
  240. {
  241. threads[i].join();
  242. }
  243.  
  244. printf("finished simulation\n");
  245.  
  246. delete neural_sync;
  247.  
  248. printf("building results\n");
  249.  
  250. /*fstream file_x("trace_x.bin", ios::out|ios::binary);
  251. fstream file_y("trace_y.bin", ios::out|ios::binary);
  252. for(unsigned int i = 0;i < brain.size();i++)
  253. {
  254. tmp = brain[i];
  255. for(unsigned int u = 0;u < brain[i]->neurons.size();u++)
  256. {
  257. for(unsigned int q = 0;q < brain[i]->neurons[u]->spikes.size();q++)
  258. {
  259. file_y.write((char*)&brain[i]->neurons[u]->id, sizeof(int));
  260. file_x.write((char*)&brain[i]->neurons[u]->spikes[q], sizeof(double));
  261. }
  262. }
  263. }
  264. file_x.close();
  265. file_y.close();*/
  266.  
  267. printf("built results\n");
  268. }
  269.  
  270. #endif
Reply With Quote Quick reply to this message  
Join Date: Feb 2008
Posts: 632
Reputation: daviddoria is a jewel in the rough daviddoria is a jewel in the rough daviddoria is a jewel in the rough 
Solved Threads: 46
daviddoria daviddoria is offline Offline
Practically a Master Poster

Re: Function pointer suddenly causes segmentation fault

 
0
  #2
Jul 9th, 2009
I realize this is quite an odd/complicated problem, but can you reduce the amount of code necessary to produce it? Maybe you can play around and remove as many lines as possible and still produce the error. Often that will help you isolate the bug yourself, or if not, then it's much easier for us to dig in.
Reply With Quote Quick reply to this message  
Join Date: Jul 2008
Posts: 49
Reputation: OffbeatPatriot is an unknown quantity at this point 
Solved Threads: 0
OffbeatPatriot OffbeatPatriot is offline Offline
Light Poster

Re: Function pointer suddenly causes segmentation fault

 
0
  #3
Jul 9th, 2009
I don't know if this is drastically simpler, I took almost 70 lines out of brain.h but it is now strictly a single threaded program.

I wanted to make it simpler but I found two simplifications that made the program work, see below.

Brain.h
  1. #ifndef NEURON_GROUP_H_INCLUDED
  2. #define NEURON_GROUP_H_INCLUDED
  3.  
  4. #include <vector>
  5. #include <map>
  6. #include <math.h>
  7.  
  8. #include <boost/random.hpp>
  9. #include <boost/bind.hpp>
  10.  
  11. using namespace std;
  12.  
  13. boost::mt19937 range;
  14.  
  15. boost::uniform_real<> values(0, 1);
  16. boost::variate_generator<boost::mt19937&, boost::uniform_real<> > uniform(range, values);
  17.  
  18. boost::normal_distribution<> values_normal(0, 1);
  19. boost::variate_generator<boost::mt19937&, boost::normal_distribution<> > normal(range, values_normal);
  20.  
  21. class Cluster;
  22. class Neuron;
  23.  
  24. class Connection
  25. {
  26. public:
  27. Cluster *target;
  28. double density, size;
  29. double (*weights)();
  30. Connection(Cluster *target, double (*weights)(), double density, double size)
  31. {
  32. this->target = target;
  33. this->weights = weights;
  34. this->density = density;
  35. this->size = size;
  36. }
  37. };
  38.  
  39. class Injection
  40. {
  41. public:
  42. double density, size;
  43. double (*source)(double);
  44. Injection(double (*source)(double), double density, double size)
  45. {
  46. this->source = source;
  47. this->density = density;
  48. this->size = size;
  49. }
  50. };
  51.  
  52. class Cluster
  53. {
  54. public:
  55. vector<Neuron*> neurons;
  56. vector<Connection*> connections;
  57. vector<Injection*> injections;
  58. int neuron_num, connection_num, injection_num;
  59. double (*a)(), (*b)(), (*c)(), (*d)();
  60. Cluster(int neuron_num, double (*a)(),double (*b)(),double (*c)(),double (*d)())
  61. {
  62. this->neuron_num = neuron_num;
  63. this->a = a;
  64. this->b = b;
  65. this->c = c;
  66. this->d = d;
  67. }
  68. void connect(Cluster *target, double (*weights)(), double density = 1, double size = 1)
  69. {
  70. connections.push_back(new Connection(target, weights, density, size));
  71. }
  72. void inject(double (*source)(double), double density = 1, double size = 1)
  73. {
  74. injections.push_back(new Injection(source, density, size));
  75. }
  76. };
  77.  
  78. class Neuron
  79. {
  80. public:
  81. double v, u, a, b, c, d, current, du, dv;
  82. double x;
  83. vector<double> pre;
  84. int id;
  85. vector<int> fired;
  86. vector<int*> post;
  87. vector<double (*)(double)> injections;
  88. vector<double> spikes;
  89. Neuron(Cluster *cluster, int id)
  90. {
  91. v = -55;
  92. u = 0;
  93. this->id = id;
  94. x = uniform();
  95. a = cluster->a();
  96. b = cluster->b();
  97. c = cluster->c();
  98. d = cluster->d();
  99. }
  100. void integrate(double time)
  101. {
  102. current = 0;
  103. for(unsigned int i = 0;i < injections.size();i++)
  104. {
  105. current += injections[i](time);
  106. }
  107. du = a*(b*v - u);
  108. v += .5*(0.04*pow(v, 2) + 5*v + 140 - u + current);
  109. v += .5*(0.04*pow(v, 2) + 5*v + 140 - u + current);
  110. u += du;
  111. if(v >= 30)
  112. {
  113. v = c;
  114. u += d;
  115. for(unsigned int q = 0;q < post.size();q++)
  116. {
  117. *post[q] = 1;
  118. }
  119. spikes.push_back(time);
  120. }
  121. }
  122. void sum()
  123. {
  124. for(unsigned int q = 0;q < pre.size();q++)
  125. {
  126.  
  127. if(fired[q])
  128. {
  129. v += pre[q];
  130. fired[q] = 0;
  131. }
  132. }
  133. }
  134. };
  135.  
  136. void main_loop(vector<Neuron*> neurons, double time_limit, double resolution)
  137. {
  138. for(double t = 0;t < time_limit;t += resolution)
  139. {
  140. printf("simulating %f\n", t);
  141. for(unsigned int i = 0;i < neurons.size();i++)
  142. {
  143. neurons[i]->integrate(t);
  144. }
  145. for(unsigned int i = 0;i < neurons.size();i++)
  146. {
  147. neurons[i]->sum();
  148. }
  149. }
  150. }
  151.  
  152. void simulate(vector<Cluster*> brain, double time_limit, double resolution = 1)
  153. {
  154. vector<Neuron*> neurons;
  155. Cluster *tmp;
  156. int id = 0, total_neurons = 0;
  157. Neuron *neuron;
  158. for(unsigned int i = 0;i < brain.size();i++)
  159. {
  160. tmp = brain[i];
  161. total_neurons += tmp->neuron_num;
  162. for(int u = 0;u < tmp->neuron_num;u++)
  163. {
  164. neuron = new Neuron(tmp, id++);
  165. tmp->neurons.push_back(neuron);
  166. neurons.push_back(neuron);
  167. }
  168. }
  169.  
  170. printf("building neurons\n");
  171. Neuron *from_neuron, *to_neuron;
  172. for(unsigned int i = 0;i < brain.size();i++)
  173. {
  174. tmp = brain[i];
  175. for(unsigned int u = 0;u < tmp->neurons.size();u++)
  176. {
  177. from_neuron = tmp->neurons[u];
  178. for(unsigned int q = 0;q < tmp->connections.size();q++)
  179. {
  180. for(unsigned int p = 0;p < tmp->connections[q]->target->neurons.size();p++)
  181. {
  182. to_neuron = tmp->connections[q]->target->neurons[p];
  183. to_neuron->pre.push_back(tmp->connections[q]->weights());
  184. to_neuron->fired.push_back(0);
  185. from_neuron->post.push_back(&to_neuron->fired.back());
  186. }
  187. }
  188. for(unsigned int q = 0;q < tmp->injections.size();q++)
  189. {
  190. from_neuron->injections.push_back(tmp->injections[q]->source);
  191. }
  192. }
  193. }
  194.  
  195. printf("starting simulation\n");
  196.  
  197. main_loop(neurons, time_limit, resolution);
  198.  
  199. printf("finished simulation\n");
  200. }
  201.  
  202. #endif

if I removed lines 107-120 or if I remove lines 178-187 the program runs fine.
Reply With Quote Quick reply to this message  
Join Date: Jul 2008
Posts: 49
Reputation: OffbeatPatriot is an unknown quantity at this point 
Solved Threads: 0
OffbeatPatriot OffbeatPatriot is offline Offline
Light Poster

Re: Function pointer suddenly causes segmentation fault

 
0
  #4
Jul 10th, 2009
I've gotten it to work now. I'm really not sure what was wrong with what I did but I also have to admit I was treading programming waters I didn't under stand too well.

I wanted to have a multithreaded program so every neuron in my simulation had a vector of integers, one integer for each neuron that could send input to it, this vector was called fired. Each neuron also had a vector of integer pointers, and each pointer in these vectors pointed to an integer in the fired vector of each neuron they could send input to, call this vector post. So when a neuron sent input to another neuron it dereferenced each pointer in in the post vector and set the integer to 1. Next, each neuron would check the integers in the fired vector to see if a neuron fired and take appropriate action.

Strangely, I don't see how any of this could be related to my original problem...but the program works.
Reply With Quote Quick reply to this message  
Reply

This thread has been marked solved.
Perhaps start a new thread instead?
Message:


Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC