943,929 Members | Top Members by Rank

Ad:
  • C++ Discussion Thread
  • Marked Solved
  • Views: 1180
  • C++ RSS
Jul 9th, 2009
0

Function pointer suddenly causes segmentation fault

Expand Post »
Basically I'm trying to run a simulation of neurons and this is the code that gets run in the main loop of it.

c++ Syntax (Toggle Plain Text)
  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.

c++ Syntax (Toggle Plain Text)
  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
c++ Syntax (Toggle Plain Text)
  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
c++ Syntax (Toggle Plain Text)
  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
Similar Threads
Reputation Points: 15
Solved Threads: 0
Junior Poster in Training
OffbeatPatriot is offline Offline
68 posts
since Jul 2008
Jul 9th, 2009
0

Re: Function pointer suddenly causes segmentation fault

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.
Featured Poster
Reputation Points: 437
Solved Threads: 204
Posting Virtuoso
daviddoria is offline Offline
1,968 posts
since Feb 2008
Jul 9th, 2009
0

Re: Function pointer suddenly causes segmentation fault

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
c++ Syntax (Toggle Plain Text)
  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.
Reputation Points: 15
Solved Threads: 0
Junior Poster in Training
OffbeatPatriot is offline Offline
68 posts
since Jul 2008
Jul 10th, 2009
0

Re: Function pointer suddenly causes segmentation fault

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.
Reputation Points: 15
Solved Threads: 0
Junior Poster in Training
OffbeatPatriot is offline Offline
68 posts
since Jul 2008

This thread is solved

Either the thread starter or a moderator has marked this thread as solved. You can most likely trust the responses and answers given. There is most likely no reason for any further responses to be posted here. If you have a related question, please start a new thread in this forum instead.

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C++ Forum Timeline: Safe Array
Next Thread in C++ Forum Timeline: Exceptional handling in c++





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC