"Christmas - the time to fix the computers of your loved ones" « Lord Wyrm

MySQL UDF in C

rappit 23.04.2012 - 10:27 2394 4
Posts

rappit

Bloody Newbie
Registered: Mar 2003
Location: AUSTRIA
Posts: 38
Hallo,

ich versuche ein UDF für MySQL zu schreiben und mein C-Wissen ist leider etwas eingerostet ;)

Code: C
typedef char** stringArray;
stringArray MallocStringArray(size_t SizeOfOneString, size_t StringCount)
{
  char** t=malloc(StringCount*sizeof(char*));
  size_t i;
  for(i=0;i<StringCount;++i)
    t[i]=malloc(SizeOfOneString);
  return t;
}

void FreeStringArray(stringArray StringArray, size_t StringCount)
{
  size_t i;
  for(i=0;i<StringCount;++i)
    free(StringArray[i]);
  free(StringArray);
}

void levenshtein_w_deinit(UDF_INIT *initid) {
  if (initid->ptr != NULL) {
    free(initid->ptr);
  }
}



my_bool levenshtein_w_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
  if ((args->arg_count != 3) ||
      (args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT || args->arg_type[2] != INT_RESULT)) {
    strcpy(message, "Function requires 3 arguments, (string, string, int)");
    return 1;
  }

  initid->max_length = LEVENSHTEIN_MAX;
  initid->maybe_null = 0; //doesn't return null
  
   fprintf(stderr, "\n\nSTART FUNCTION\n\n");
   fflush(stderr);  


  return 0;
}


longlong levenshtein_w(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { 

  
  if (args->args[0] == NULL || args->args[1] == NULL || args->args[2] == NULL)
     return 0;

  int lv_distance = *(int *) args->args[2];
  
  
  char* suchbegriff=malloc(250); 
  char* keywords=malloc(250); 
  
  suchbegriff = args->args[0];
  keywords = args->args[1]; 

  //Log for Testing
  fprintf(stderr, "Uebergabe: %s (%p) \n", args->args[1], args->args[1]);
  fflush(stderr); 

  stringArray strings;
  strings=MallocStringArray(250,30); 


  // Suchbegriff spliten und in string Array speichern  

  // ....

  return 1;

}

Laut Doku sollt bei einem Aufruf einer UDF folgendes passiert
init();
levenshtein_w();
deinint();

Wenn ich jetzt folgendes aufrufe

SELECT levenshtein_w(
'kommunikationsexpertin', suchstring_levenshtein, 2
)
FROM `stellengesuch_suchstring2`
LIMIT 4


Schaut die Aufruffolge allerdings so aus

init();
levenshtein_w();
levenshtein_w();
levenshtein_w();
levenshtein_w();
deinint();

Wie oben ersichtlich im Code logge ich den Übergabeparamter weg. Log:

Uebergabe: mitarbeiterinsexpertinbsleiteresuch (0xaf7b530)
Uebergabe: verkaufsleiter vertriebsleiteresuch (0xaf14280)
Uebergabe: kommunikationsexpertinbsleiteresuch (0xaf14280)


Wie man sieht bleibt bei jedem Auruf der alte String erhalten :O Wenn der neue String also kürzer als der alte ist steht der alte zum Teil auch noch im Speicher.... Wie kann das sein?


Danke, lg
Bearbeitet von rappit am 23.04.2012, 10:31

mat

Administrator
Legends never die
Avatar
Registered: Aug 2003
Location: nö
Posts: 25422
Das ist in jedem Fall komisch:

Code: C
char* suchbegriff=malloc(250); 
char* keywords=malloc(250); 

suchbegriff = args->args[0];
keywords = args->args[1];
Du machst ein malloc und dann überschreibst du den Pointer sofort wieder.

rappit

Bloody Newbie
Registered: Mar 2003
Location: AUSTRIA
Posts: 38
Zitat von mat
Das ist in jedem Fall komisch:

Code: C
char* suchbegriff=malloc(250); 
char* keywords=malloc(250); 

suchbegriff = args->args[0];
keywords = args->args[1];
Du machst ein malloc und dann überschreibst du den Pointer sofort wieder.

Hmm das dürfte wohl noch vom Testen sein.

Aber sogar wenn ich direkt args->arges[1] in das Log schreib tritt der Fehler auf.

mat

Administrator
Legends never die
Avatar
Registered: Aug 2003
Location: nö
Posts: 25422
So wie es aussieht, macht er dir einfach kein '\0' am Schluss des Strings. In der Dokumentation gibt es einen lengths-Parameter im Argument-Array:
Zitat
unsigned long *lengths

For the initialization function, the lengths array indicates the maximum string length for each argument. You should not change these. For each invocation of the main function, lengths contains the actual lengths of any string arguments that are passed for the row currently being processed. For arguments of types INT_RESULT or REAL_RESULT, lengths still contains the maximum length of the argument (as for the initialization function).
Wenn das Argument also ein String ist, dann wirst du diesen selber herausholen müssen. Am besten wahrscheinlich gleich kopieren. Würde es so machen:

Code: C
char szBuffer[LEVENSHTEIN_MAX];

*szBuffer = 0;
strncat(args->args[0],szBuffer,args->lengths[0]);

rappit

Bloody Newbie
Registered: Mar 2003
Location: AUSTRIA
Posts: 38
Danke, danke, danke - das wars!

Code: C
  char suchbegriff[250];
  *suchbegriff = 0;
  char keywords[1000];
  *keywords = 0;


  strncat(suchbegriff,args->args[0],(args->lengths[0] > 250) ? 250 :   args->lengths[0]); 
  strncat(keywords,args->args[1],(args->lengths[1] > 1000) ? 1000 : args->lengths[1]); 
  

So funktionierts. Hab die args-Länge mitgeloggt und da sieht man schön dass dort die String-Länge passt.

Vielen Dank nochmal!
Kontakt | Unser Forum | Über overclockers.at | Impressum | Datenschutz