0

Objective-C で C API をラップしようとしていますが、objc_release で EXC_BAD_ACCESS を取得しています。

フィールド.h:

#ifdef __cplusplus
extern "C" {
#endif

struct sc_field
{
    char *title;
};

typedef struct sc_field sc_field_t;

sc_field_t* sc_create_field();
void sc_destroy_field(sc_field_t *field);
const char* sc_get_title(const sc_field_t *field);
void sc_set_title(sc_field_t *field, const char *title);

#ifdef __cplusplus
}

#include <string>

class Field
{
public:
    explicit Field();
    virtual ~Field();

    std::string title() const;
    void setTitle(const std::string &title);

private:
    class Private;
    Private *d;
};

Field.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Field.h"

sc_field_t* sc_create_field()
{
    sc_field_t *field = (sc_field_t*)malloc(sizeof(sc_field_t));
    field->title = (char*)calloc(1, sizeof(char));
    return field;
}

void sc_destroy_field(sc_field_t *field)
{
    if (field)
    {
        free(field->title);
        free(field);
    }
}

const char* sc_get_title(const sc_field_t *field)
{
    if (!field)
    {
        fprintf(stderr, "%s: fatal error, field is NULL\n", __FUNCTION__);
        return NULL;
    }

    return field->title;
}

void sc_set_title(sc_field_t *field, const char *title)
{
    if (!field)
    {
        fprintf(stderr, "%s: fatal error, field is NULL\n", __FUNCTION__);
        return;
    }

    field->title = (char*)realloc(field->title, sizeof(char) * sizeof(title));
    strcpy(field->title, title);
}

SCField.h:

#import "Field.h"
#import <Foundation/Foundation.h>

@interface SCField : NSObject
{
@private
    sc_field_t *field;
}

@property (nonatomic, copy) NSString *title;

- (id)init;
- (id)initWithTitle:(NSString *)title;
- (void)dealloc;

@end

SCField.m:

#import "SCField.h"

@implementation SCField

@synthesize title;

- (id)init
{
    self = [super init];
    if (self)
    {
        field = sc_create_field();
    }

    return self;
}

- (id)initWithTitle:(NSString *)aTitle
{
    self = [self init];
    if (self)
    {
        [self setTitle:aTitle];
    }

    return self;
}

- (void)dealloc
{
    sc_destroy_field(field);
    [super dealloc];
}

- (NSString *)title
{
    return [NSString stringWithUTF8String:sc_get_title(field)];
}

- (void)setTitle:(NSString *)aTitle
{
    sc_set_title(field, [aTitle UTF8String]);
}

@end

テスト:

SCField *field = [[SCField alloc] initWithTitle:@"Hello world!"];
NSLog(@"%@\n", [field title]);
[field release];

SCField インスタンスを解放するまで、コードは正常に動作するようです。NSString* を SCField に直接格納しているかのように、タイトルと setTitle: の実装を削除すると、コードは正常に動作します (@property でコピーする代わりに割り当てを試みましたが、うまくいきませんでした)。私は何を間違っていますか?

4

2 に答える 2

3

問題は、UTF8Stringを呼び出すと、自動解放されるメモリが得られることだと思います(ドキュメントによると)。

realloc()inを使用するのではなく、新しいバッファsc_set_title()だけをコピーしてコピーします。malloc()また、realloc()とにかくパラメーターが正しくないため、おそらくノーオペレーションになります。割り当てる必要がありstrlen(title) + 1ます。sizeof(char)sizeof は、コンパイラに 1 ( ) * 4 バイト ( sizeof(title)- ポインター)を与えるように要求しているだけなので、何もしません。

于 2012-12-12T09:08:49.407 に答える
0

を使用しgetCString:maxLength:encoding:ます。バッファの文字列の長さをバイト単位で取得するには、lengthOfBytesUsingEncoding:(takes O(n) time) またはmaximumLengthOfBytesUsingEncoding:(takes O(1) time) を使用します。

于 2012-12-12T09:16:00.057 に答える