user1310873
user1310873

Reputation: 389

Using std::vector with Igraph

I've been trying to find a really function that let me convert from std::vector of vector to igraph_vector_ptr_t and the opposite way.

The reason is, there are different classes like a std::sort, std::unique and others, that let us manipulate vectors, this function do not exist in Igraph libraries.

The next code only show the code to convert from std::vector to igraph_vector_ptr_t, the problem is that it doesn't work, please help me to help me to improve it.

#include <igraph.h>
#include <fstream>
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <algorithm>

using namespace std;

void print_vector(igraph_vector_t *v, FILE *f) {
  long int i;
  long int l=igraph_vector_size(v);
  for (i=0; i<l; i++) {
    fprintf(f, " %li", (long int) VECTOR(*v)[i]);
  }
  fprintf(f, "\n");
}

void Stl_To_Igraph_vector_ptr_t(std::vector< std::vector< long int > > & vectR, igraph_vector_ptr_t * vl) {
      long int i,j,n;

      igraph_vector_t vt;
      igraph_vector_init(&vt,4);
      for (i = 0; i< 2; i++) {
            for (j = 0; j< 4; j++) {
                //cout << vectR.at(i).at(j) << " ";
                VECTOR(vt)[j]=vectR.at(i).at(j);
            }
            //cout<<endl;
            igraph_vector_ptr_set(vl, i,&vt);
      }
}

int main() {

  // Set STL Vectors
  std::vector< std::vector< long int > > vectR;
  std::vector<long int> vectRi1,vectRi2;
  long int myarray1 [] = { 1,2,3,4 };
  long int myarray2 [] = { 5,6,7,8 };

  vectRi1.insert(vectRi1.begin(), myarray1,  myarray1+4);
  vectRi2.insert(vectRi2.begin(), myarray2,  myarray2+4);

  vectR.push_back(vectRi1);
  vectR.push_back(vectRi2);

  // Convert From Stl vector to Igraph_vector_ptr_t
  igraph_vector_ptr_t vIgraph;

  igraph_vector_ptr_init(&vIgraph, 2);
  Stl_To_Igraph_vector_ptr_t(vectR, &vIgraph);

  // Print and distroyed
  long int i;
  for (i=0; i<igraph_vector_ptr_size(&vIgraph); i++) {
    print_vector((igraph_vector_t *)VECTOR(vIgraph)[i],stdout);
    igraph_vector_destroy((igraph_vector_t *)VECTOR(vIgraph)[i]);
    free((igraph_vector_t *)VECTOR(vIgraph)[i]);
  }

  return 0;
}

Ok this is part of the solution but I have a problem in valgrind,

#include <igraph.h>

#include <stdlib.h>

int print_vector(igraph_vector_t *v) {
  long int i, l=igraph_vector_size(v);
  for (i=0; i<l; i++) {
    printf(" %li", (long int) VECTOR(*v)[i]);
  }
  printf("\n");
}

void convert(igraph_vector_ptr_t * vecs){
    long int i,j;
    igraph_vector_t *v;
    v = (igraph_vector_t*)calloc(igraph_vector_ptr_size(vecs), sizeof(igraph_vector_t));
    for(i=0; i<igraph_vector_ptr_size(vecs); i++)
    {
      igraph_vector_init(v + i,10);
      for(j=0; j<igraph_vector_size(v); j++){
          VECTOR(*(v+i))[j]=i+j;
      }
      igraph_vector_ptr_set(vecs,i,(v + i));
    }


}

int main() {
  igraph_vector_ptr_t vecs;
  long int i;

  igraph_vector_ptr_init(&vecs, 3);
  for (i=0; i<igraph_vector_ptr_size(&vecs); i++) {
    VECTOR(vecs)[i] = malloc(sizeof(igraph_vector_t));
    igraph_vector_init( (igraph_vector_t*)VECTOR(vecs)[i], 3);
  }

  convert(&vecs);

  for (i=0; i<igraph_vector_ptr_size(&vecs); i++) {
    print_vector( (igraph_vector_t*)VECTOR(vecs)[i]);
    igraph_vector_destroy( (igraph_vector_t*)VECTOR(vecs)[i]);
    //free(VECTOR(vecs)[i]);
  }

  igraph_vector_ptr_destroy(&vecs);
  return 0;

}

and the output of valgrind is:

user@pc:~/workSpalceIgraphCpp/proyIgraph$ valgrind --leak-check=full  -v --track-origins=yes --show-reachable=yes  ./example
==12439== Memcheck, a memory error detector
==12439== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==12439== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==12439== Command: ./example
==12439== 
--12439-- Valgrind options:
--12439--    --suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp
--12439--    --leak-check=full
--12439--    -v
--12439--    --track-origins=yes
--12439--    --show-reachable=yes
--12439-- Contents of /proc/version:
--12439--   Linux version 2.6.32-35-generic-pae (buildd@vernadsky) (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) ) #78-Ubuntu SMP Tue Oct 11 17:01:12 UTC 2011
--12439-- Arch and hwcaps: X86, x86-sse1-sse2
--12439-- Page sizes: currently 4096, max supported 4096
--12439-- Valgrind library directory: /usr/lib/valgrind
--12439-- Reading syms from /lib/ld-2.11.1.so (0x4000000)
--12439-- Reading debug info from /lib/ld-2.11.1.so ..
--12439-- .. CRC mismatch (computed 45f50ae1 wanted 137bc614)
--12439-- Reading debug info from /usr/lib/debug/lib/ld-2.11.1.so ..
--12439-- Reading syms from /home/rvaca/workSpalceIgraphCpp/proyIgraph/example (0x8048000)
--12439-- Reading syms from /usr/lib/valgrind/memcheck-x86-linux (0x38000000)
--12439--    object doesn't have a dynamic symbol table
--12439-- Reading suppressions file: /usr/lib/valgrind/debian-libc6-dbg.supp
--12439-- Reading suppressions file: /usr/lib/valgrind/default.supp
--12439-- REDIR: 0x40160b0 (index) redirected to 0x3803e9b3 (vgPlain_x86_linux_REDIR_FOR_index)
--12439-- Reading syms from /usr/lib/valgrind/vgpreload_core-x86-linux.so (0x401f000)
--12439-- Reading syms from /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so (0x4022000)
==12439== WARNING: new redirection conflicts with existing -- ignoring it
--12439--     new: 0x040160b0 (index               ) R-> 0x04025c30 index
--12439-- REDIR: 0x4016290 (strlen) redirected to 0x4026070 (strlen)
--12439-- Reading syms from /usr/local/lib/libigraph.so.0.0.0 (0x402b000)
--12439-- Reading syms from /usr/lib/libstdc++.so.6.0.13 (0x4213000)
--12439--    object doesn't have a symbol table
--12439-- Reading syms from /lib/tls/i686/cmov/libm-2.11.1.so (0x4308000)
--12439-- Reading debug info from /lib/tls/i686/cmov/libm-2.11.1.so ..
--12439-- .. CRC mismatch (computed a765a73c wanted 8d13be57)
--12439-- Reading debug info from /usr/lib/debug/lib/tls/i686/cmov/libm-2.11.1.so ..
--12439-- Reading syms from /lib/libgcc_s.so.1 (0x432e000)
--12439-- Reading debug info from /lib/libgcc_s.so.1 ..
--12439-- .. CRC mismatch (computed 338494ad wanted b1d69d39)
--12439--    object doesn't have a symbol table
--12439-- Reading syms from /lib/tls/i686/cmov/libc-2.11.1.so (0x434d000)
--12439-- Reading debug info from /lib/tls/i686/cmov/libc-2.11.1.so ..
--12439-- .. CRC mismatch (computed 2236eb0a wanted a071c0c3)
--12439-- Reading debug info from /usr/lib/debug/lib/tls/i686/cmov/libc-2.11.1.so ..
--12439-- Reading syms from /usr/lib/libxml2.so.2.7.6 (0x44a8000)
--12439-- Reading debug info from /usr/lib/libxml2.so.2.7.6 ..
--12439-- .. CRC mismatch (computed 8c0a5cb7 wanted d9f96831)
--12439--    object doesn't have a symbol table
--12439-- Reading syms from /usr/lib/libgmp.so.3.5.2 (0x45d3000)
--12439-- Reading debug info from /usr/lib/libgmp.so.3.5.2 ..
--12439-- .. CRC mismatch (computed b9cf7786 wanted 4db0a849)
--12439--    object doesn't have a symbol table
--12439-- Reading syms from /lib/tls/i686/cmov/libdl-2.11.1.so (0x4634000)
--12439-- Reading debug info from /lib/tls/i686/cmov/libdl-2.11.1.so ..
--12439-- .. CRC mismatch (computed 10f03463 wanted f15a6db6)
--12439-- Reading debug info from /usr/lib/debug/lib/tls/i686/cmov/libdl-2.11.1.so ..
--12439-- Reading syms from /lib/libz.so.1.2.3.3 (0x4638000)
--12439-- Reading debug info from /lib/libz.so.1.2.3.3 ..
--12439-- .. CRC mismatch (computed 53909dc3 wanted dc0e37c9)
--12439--    object doesn't have a symbol table
--12439-- REDIR: 0x43c0b10 (rindex) redirected to 0x4025ae0 (rindex)
--12439-- REDIR: 0x43c07f0 (__GI_strlen) redirected to 0x4026050 (__GI_strlen)
--12439-- REDIR: 0x43bc660 (calloc) redirected to 0x402417f (calloc)
--12439-- REDIR: 0x43bcf40 (malloc) redirected to 0x4024e9b (malloc)
--12439-- REDIR: 0x43c32b0 (strchrnul) redirected to 0x4027510 (strchrnul)
 0 1 2 3 4 5 6 7 8 9
--12439-- REDIR: 0x43bce60 (free) redirected to 0x4024ab5 (free)
 1 2 3 4 5 6 7 8 9 10
 2 3 4 5 6 7 8 9 10 11
==12439== 
==12439== HEAP SUMMARY:
==12439==     in use at exit: 144 bytes in 7 blocks
==12439==   total heap usage: 11 allocs, 4 frees, 396 bytes allocated
==12439== 
==12439== Searching for pointers to 7 not-freed blocks
==12439== Checked 425,428 bytes
==12439== 
==12439== 36 bytes in 1 blocks are definitely lost in loss record 1 of 3
==12439==    at 0x402425F: calloc (vg_replace_malloc.c:467)
==12439==    by 0x80488C8: convert(s_vector_ptr*) (pregunta3.cpp:223)
==12439==    by 0x8048A11: main (pregunta3.cpp:246)
==12439== 
==12439== 72 bytes in 3 blocks are indirectly lost in loss record 2 of 3
==12439==    at 0x402425F: calloc (vg_replace_malloc.c:467)
==12439==    by 0x40C9A78: igraph_vector_init (vector.pmt:123)
==12439==    by 0x80489E9: main (pregunta3.cpp:243)
==12439== 
==12439== 108 (36 direct, 72 indirect) bytes in 3 blocks are definitely lost in loss record 3 of 3
==12439==    at 0x4024F20: malloc (vg_replace_malloc.c:236)
==12439==    by 0x80489C8: main (pregunta3.cpp:242)
==12439== 
==12439== LEAK SUMMARY:
==12439==    definitely lost: 72 bytes in 4 blocks
==12439==    indirectly lost: 72 bytes in 3 blocks
==12439==      possibly lost: 0 bytes in 0 blocks
==12439==    still reachable: 0 bytes in 0 blocks
==12439==         suppressed: 0 bytes in 0 blocks
==12439== 
==12439== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 27 from 6)
--12439-- 
--12439-- used_suppression:     27 dl-hack3-cond-1
==12439== 
==12439== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 27 from 6)

what's the problem?

Upvotes: 0

Views: 1001

Answers (1)

Tam&#225;s
Tam&#225;s

Reputation: 48071

First of all, igraph is a C library, not a C++ library. C does not have anything like the STL, so that's why there are no conversion functions between an igraph_vector_t and an std::vector. You have to write the conversion functions yourself.

Second, since vt is a vector allocated on the stack within Stl_To_Igraph_vector_ptr_t (i.e. you just declared it as a local variable and did not allocate it using malloc), it will cease to exist as soon as the function returns. You store a pointer to vt in your igraph_vector_ptr_t, but that pointer becomes invalid when you exit from the function, that's why you are getting an error later. You have to make vt an igraph_vector_ptr_t, and use malloc to allocate it if you want it to outlive the conversion function.

Edit: This is how it should be done -- I haven't tested it though (no C compiler around), but it should work. These are optimized for readability and not for performance (e.g. you could do Stl_To_Igraph_vector_T using std::copy):

void Stl_To_Igraph_vector_t(std::vector<long int>& vectR, igraph_vector_t* v) {
    size_t n = vectR.size();

    /* Make sure that there is enough space for the items in v */
    igraph_vector_resize(v, n);

    /* Copy all the items */
    for (size_t i = 0; i < n; i++) {
        VECTOR(*v)[i] = vectR[i];
    }
}

void Stl_To_Igraph_vector_ptr_t(std::vector< std::vector<long int> >& vectR, igraph_vector_ptr_t* vl) {
    size_t n = vectR.size();

    /* Make sure that there is enough space for the items in vl */
    igraph_vector_ptr_resize(vl, n);

    /* Copy all the items */
    for (size_t i = 0; i < n; i++) {
         VECTOR(*vl)[i] = (igraph_vector_t*)malloc(sizeof(igraph_vector_t));
         igraph_vector_init(VECTOR(*vl)[i]);
         Stl_To_Igraph_vector_t(vectR[i], VECTOR(*vl)[i]);
    }
}

vl must be initialized to zero size before calling Stl_To_Igraph_vector_ptr_t. When you are done with using vl, you must call igraph_vector_destroy and free on all its elements.

Upvotes: 1

Related Questions