问题
I write this code, repeatc for repeat char to char array. it works.
repeats for repeat string N times to an string array. but repeat string to string array core dumped.
A, A, A,
AB, AB, AB,
*** Error in `./untitled': free(): invalid pointer: 0x0000000000400f3d ***
....
....
Aborted (core dumped)
why? my code:
// --cc='gcc'
[indent=4]
init
var carray = repeatc ('A', 3)
for i in carray do stdout.printf ("%c, ", i)
// A, A, A
stdout.putc ('\n')
var sarray = repeats ("AB", 3)
for i in sarray do stdout.printf ("%s, ", i)
stdout.putc ('\n')
def repeatc (e: char, n: int): array of char
var a = new array of char[n]
Memory.copy (a, &e, sizeof (char))
Memory.copy (&a[1], a, sizeof (char) * (n - 1)) // gcc
return a
def repeats (e: string, n: int): array of string
var a = new array of string[n]
// WORKS: for var i = 0 to (n - 1) do a[i] = e
// Memory.copy HOW TO?
// (CORE DUMPED)
Memory.copy (a, &e, sizeof (uint8*))
Memory.copy (&a[1], a, sizeof (uint8*) * (n - 1))
return a
Why this code core dumped? and How to fix it?
回答1:
There are several things wrong with this code.
[indent=4]
init
var carray = repeatc ('A', 3)
for i in carray do stdout.printf ("%c, ", i)
// A, A, A
Actually, it prints "A, A, A, " (note the trailing comma and space). There are lots of ways to fix this, the easiest would just be to do something like stdout.puts (string.joinv (", ", sarray))
.
def repeatc (e: char, n: int): array of char
var a = new array of char[n]
Memory.copy (a, &e, sizeof (char))
Using Memory.copy (a.k.a. memcpy in C) to copy a single byte is a more than a little silly. There is absolutely no reason not to just do a[0] = e
here. It is easier and will perform better.
Memory.copy (&a[1], a, sizeof (char) * (n - 1)) // gcc
This is very wrong. You're telling it to copy sizeof (char) * (n - 1)
bytes from the location a
to 1 byte after a
. This is very different than what you seem to intend, which is to fill the rest of a with the value of the first byte in the array. In reality you shouldn't be using Memory.copy
, you should be using Memory.set
: Memory.set (a, e, n)
can replace both those Memory.copy
lines.
That said, it's likely that what you really want is a string not an array of chars. If that's the case, you can replace that whole function and just call string.nfill (3, 'A')
.
def repeats (e: string, n: int): array of string
var a = new array of string[n]
// WORKS: for var i = 0 to (n - 1) do a[i] = e
// Memory.copy HOW TO?
You still need a loop. Once you start trying to use the Memory.*
functions you're working with pointers, so you need to understand how the memory is laid out. Strings are really just arrays of characters, and arrays are just pointers to the first element in the array. When you create an array of strings, what you have is a pointer to a pointer (in C, gchar**
), not a pointer to a large contiguous block you can start copying your character data into.
I guess you're trying to use Memory.copy
instead of a loop and simple assignment to improve performance; the only thing really bad thing for performance here is that a simple assignment will call g_strdup
which will call strlen
, so you end up scanning your input string N times to calculate the length instead of once. The best you're going to get is probably something like:
var elen = e.length
for var i = 0 to (n - 1)
a[i] = (string) Memory.dup (e, (uint) elen);
If you really care about performance what you would want to do is return an array of unowned strings that all point to the same location in memory. Or, if what you're interested in is really the joined string and not the array, just do something like
def repeatwithsep (e: string, n: int, separator: string): string
var elen = e.length;
var slen = separator.length;
var a = new StringBuilder.sized ((elen * n) + (slen * (n - 1)) + 1);
for var i = 0 to (n - 1)
if i != 0
a.append_len (separator, slen)
a.append_len (e, elen)
return (owned) a.str;
来源:https://stackoverflow.com/questions/31370915/genie-howto-repeat-a-string-n-times-as-an-string-array