octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[50 character or so descriptive subject here (for reference)]


From: John W. Eaton
Subject: [50 character or so descriptive subject here (for reference)]
Date: Thu, 8 Nov 2001 23:58:35 -0600

On 18-Oct-2001, Douglas Eck <address@hidden> wrote:

| To: address@hidden
| Cc: doug
| Subject: [50 character or so descriptive subject here (for reference)]
| 
| Bug report for Octave 2.0.16.92 configured for i386-pc-linux-gnu
| 
| Description:
| -----------
| 
| Using const char * c = args(0).string_value().c_str();
| to get a string from the argument vector sometimes results
| in unpredictable results.
| 
| Repeat-By:
| ---------
| 
| /*
| This code snippet shows that using c_str() has
| unpredictable results when parsing args in an .oct file.
| 
| This might not be an octave bug (in fact, it probably isn't)
| but it took me a while to find so I wanted to submit it. 
| 
| I am running the latest debian unstable.
| 
| Here is a test run of this code on my system:
| 
| 432 ruchetta ~/beat/dynamic>mkoctfile -v bad_cstr.cc
| c++ -c -fPIC -I/usr/include/octave-2.1.34 -I/usr/include/octave-2.1.34/octave 
-I/usr/include -mieee-fp -fno-implicit-templates -O2 bad_cstr.cc -o bad_cstr.o
| c++ -shared -o bad_cstr.oct bad_cstr.o
| 433 ruchetta ~/beat/dynamic>octave
| GNU Octave, version 2.1.34 (i386-pc-linux-gnu).
| Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 John W. Eaton.
| This is free software with ABSOLUTELY NO WARRANTY.
| For details, type `warranty'.
| 
| *** This is a development version of Octave.  Development releases
| *** are provided for people who want to help test, debug, and improve
| *** Octave.
| ***
| *** If you want a stable, well-tested version of Octave, you should be
| *** using one of the stable releases (when this development release
| *** was made, the latest stable version was 2.0.16).
| 
| PS1 = Octave >>
| PS2 =
| beep_on_error = 0
| default_save_format = mat-binary
| define_all_return_values = 0
| do_fortran_indexing = 0
| empty_list_elements_ok = 1
| fixed_point_format = 1
| implicit_num_to_str_ok = 1
| implicit_str_to_num_ok = 1
| ok_to_lose_imaginary_part = 1
| page_screen_output = 0
| prefer_column_vectors = 0
| prefer_zero_one_indexing = 1
| print_empty_dimensions = 0
| treat_neg_dim_as_zero = 1
| warn_function_name_clash = 0
| whitespace_in_literal_matrix = traditional
| Octave >> 
bad_cstr("12345678901234567890123456789012345678901234567890123456789012345678901234567890")
| Test 1 with broken c_str()
| Incoming char * c is 7890123456789012345678901234567890123456789012345678
|      New char * n1 is 
12345678901234567890123456789012345678901234567890123456789012345678
| 
| Test 2 with explicit copy from the string
|  Old string s is 
12345678901234567890123456789012345678901234567890123456789012345678901234567890
| New char * n2 is 
12345678901234567890123456789012345678901234567890123456789012345678901234567890
| Octave >>
| */
| 
| #include <octave/oct.h>
| 
| 
| DEFUN_DLD (bad_cstr, args, ,
|          "call like this: cpystr(string x) where x is a long string as in 
this example: 
|             
bad_cstr(\"12345678901234567890123456789012345678901234567890123456789012345678901234567890\")
|             ") 
| {
|   octave_value_list retval;
|   const char * c = args(0).string_value().c_str();
|   int sz=strlen(c);
|   char * n1 = new char[sz];
|   strcpy(n1,c);
|   cout << "Test 1 with broken c_str() " << endl;
|   cout << "Incoming char * c is " << c << endl;
|   cout << "     New char * n1 is "  << n1 << endl;
| 
|   cout << endl << "Test 2 with explicit copy from the string " << endl;
|   string s = args(0).string_value();
|   char * n2 = new char[sz];
|   for (int i=0;i<sz;i++) 
|     n2[i]=s[i];
|   cout << " Old string s is " << s << endl;
|   cout << "New char * n2 is " << n2 << endl;
| 
|   return retval;
| }
| 
| 
| Fix:
| ---
| 
|  I worked around it by doing explicit copies from the
|  std::string rather than the char * from c_str(). 
|  Perhaps (probably?) this is a bug in my debian distro,
|  not in octave.

I don't think it is a bug in Octave.  I see a couple of problems with
your code.  First, you haven't left room for the terminating NUL
character in the C strings, and when you copied it (this is a good
argument against C strings and in favor of C++ string objects, IMHO).

Also, there seems to be a problem with the lifetime of temporaries.
If you write

  string s = args(0).string_value();
  const char *c = s.c_str();

instead of just

  const char *c = args(0).string_value().c_str();

then it seems to work correctly.  Here's my modified fucntion that
seems to work:

#include <octave/oct.h>


DEFUN_DLD (bad_cstr, args, ,
           "call like this: cpystr(string x) where x is a long string as in 
this example: 
            
bad_cstr(\"12345678901234567890123456789012345678901234567890123456789012345678901234567890\")
            ") 
{
  octave_value_list retval;
  string s = args(0).string_value();
  const char * c = s.c_str();
  int sz=strlen(c);
  char * n1 = new char[sz] + 1;
  strcpy(n1,c);
  cout << "Test 1 with broken c_str() " << endl;
  cout << "Incoming char * c is " << c << endl;
  cout << "     New char * n1 is "  << n1 << endl;

  cout << endl << "Test 2 with explicit copy from the string " << endl;
  char * n2 = new char[sz] + 1;
  for (int i=0;i<sz;i++) 
    n2[i]=s[i];
  n2[sz] = '\0';
  cout << " Old string s is " << s << endl;
  cout << "New char * n2 is " << n2 << endl;

  return retval;
}


jwe



reply via email to

[Prev in Thread] Current Thread [Next in Thread]