Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  MemoryTrace.cpp

  Sprache: C
 

/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include <inttypes.h>
#include <stdio.h>
#include <unistd.h>

#include <string>

#include <android-base/stringprintf.h>

#include <memory_trace/MemoryTrace.h>

namespace memory_trace {

// This is larger than the maximum length of a possible line.
constexpr size_t kBufferLen = 256;

bool FillInEntryFromString(const std::string& line, Entry& entry, std::string&&nbsp;error) {
  // All lines have this format:
  //   TID: ALLOCATION_TYPE POINTER [START_TIME_NS END_TIME_NS]
  // where
  //   TID is the thread id of the thread doing the operation.
  //   ALLOCATION_TYPE is one of malloc, calloc, memalign, realloc, free, thread_done
  //   POINTER is the hex value of the actual pointer
  //   START_TIME_NS is the start time of the operation in nanoseconds.
  //   END_TIME_NS is the end time of the operation in nanoseconds.
  // The START_TIME_NS and END_TIME_NS are optional parameters, either both
  // are present are neither are present.
  int op_prefix_pos = 0;
  char name[128];
  if (sscanf(line.c_str(), "%d: %127s %" SCNx64 " %n", &entry.tid, name, &entry.ptr,
             &op_prefix_pos) != 3) {
    error = "Failed to process line: " + line;
    return false;
  }

  entry.u.old_ptr = 0;
  entry.present_bytes = -1;
  entry.start_ns = 0;
  entry.end_ns = 0;

  // Handle each individual type of entry type.
  std::string type(name);
  if (type == "thread_done") {
    //   TID: thread_done 0x0 [END_TIME_NS]
    // Where END_TIME_NS is optional.
    entry.type = THREAD_DONE;
    entry.start_ns = 0;
    // Thread done has an optional time which is when the thread ended.
    // This is the only entry type that has a single timestamp.
    int n_match = sscanf(&line[op_prefix_pos], " %" SCNd64, &entry.end_ns);
    entry.start_ns = 0;
    if (n_match == EOF) {
      entry.end_ns = 0;
    } else if (n_match != 1) {
      error = "Failed to read thread_done end time: " + line;
      return false;
    }
    return true;
  }

  bool read_present_bytes = false;
  int args_offset = 0;
  const char* args = &line[op_prefix_pos];
  if (type == "malloc") {
    // Format:
    //   TID: malloc POINTER SIZE_OF_ALLOCATION [START_TIME_NS END_TIME_NS]
    if (sscanf(args, "%zu%n", &entry.size, &args_offset) != 1) {
      error = "Failed to read malloc data: " + line;
      return false;
    }
    entry.type = MALLOC;
  } else if (type == "free") {
    // Format:
    //   TID: free POINTER [START_TIME_NS END_TIME_NS] [PRESENT_BYTES]
    entry.type = FREE;
    read_present_bytes = true;
  } else if (type == "calloc") {
    // Format:
    //   TID: calloc POINTER ITEM_COUNT ITEM_SIZE [START_TIME_NS END_TIME_NS]
    if (sscanf(args, "%" SCNd64 " %zu%n", &entry.u.n_elements, &entry.size, &args_offset) != 2) {
      error = "Failed to read calloc data: " + line;
      return false;
    }
    entry.type = CALLOC;
  } else if (type == "realloc") {
    // Format:
    //   TID: realloc POINTER OLD_POINTER NEW_SIZE [START_TIME_NS END_TIME_NS] [PRESENT_BYTES]
    if (sscanf(args, "%" SCNx64 " %zu%n", &entry.u.old_ptr, &entry.size, &args_offset) != 2) {
      error = "Failed to read realloc data: " + line;
      return false;
    }
    read_present_bytes = true;
    entry.type = REALLOC;
  } else if (type == "memalign") {
    // Format:
    //   TID: memalign POINTER ALIGNMENT SIZE [START_TIME_NS END_TIME_NS]
    if (sscanf(args, "%" SCNd64 " %zu%n", &entry.u.align, &entry.size, &args_offset) != 2) {
      error = "Failed to read memalign data: " + line;
      return false;
    }
    entry.type = MEMALIGN;
  } else {
    error = "Unknown type " + type + ": " + line;
    return false;
  }

  // Get the optional timestamps if they exist.
  args = &args[args_offset];
  int n_match =
      sscanf(args, "%" SCNd64 " %" SCNd64 "%n", &entry.start_ns, &entry.end_ns, &args_offset);
  if (n_match == EOF) {
    return true;
  }

  if (n_match != 2) {
    error = "Failed to read timestamps: " + line;
    return false;
  }

  // Get the optional present bytes if it exists.
  if (read_present_bytes) {
    n_match = sscanf(&args[args_offset], "%" SCNd64, &entry.present_bytes);
    if (n_match != EOF && n_match != 1) {
      error = "Failed to read present bytes: " + line;
      return false;
    }
  }
  return true;
}

const char* TypeToName(const TypeEnum type) {
  switch (type) {
    case CALLOC:
      return "calloc";
    case FREE:
      return "free";
    case MALLOC:
      return "malloc";
    case MEMALIGN:
      return "memalign";
    case REALLOC:
      return "realloc";
    case THREAD_DONE:
      return "thread_done";
    default:
      return "unknown";
  }
}

static size_t FormatEntry(const Entry& entry, char* buffer, size_t buffer_len) {
  int len = snprintf(buffer, buffer_len, "%d: %s 0x%" PRIx64, entry.tid, TypeToName(entry.type),
                     entry.ptr);
  if (len < 0) {
    return 0;
  }
  size_t cur_len = len;
  bool output_present_bytes = false;
  switch (entry.type) {
    case FREE:
      len = 0;
      if (entry.present_bytes != -1) {
        output_present_bytes = true;
      }
      break;
    case CALLOC:
      len = snprintf(&buffer[cur_len], buffer_len - cur_len, " %" PRIu64 " %zu", entry.u.n_elements,
                     entry.size);
      break;
    case MALLOC:
      len = snprintf(&buffer[cur_len], buffer_len - cur_len, " %zu", entry.size);
      break;
    case MEMALIGN:
      len = snprintf(&buffer[cur_len], buffer_len - cur_len, " %" PRIu64 " %zu", entry.u.align,
                     entry.size);
      break;
    case REALLOC:
      len = snprintf(&buffer[cur_len], buffer_len - cur_len, " 0x%" PRIx64 " %zu", entry.u.old_ptr,
                     entry.size);
      if (entry.present_bytes != -1) {
        output_present_bytes = true;
      }
      break;
    case THREAD_DONE:
      // Thread done only has a single optional timestamp, end_ns.
      if (entry.end_ns != 0) {
        len = snprintf(&buffer[cur_len], buffer_len - cur_len, " %" PRId64, entry.end_ns);
        if (len < 0) {
          return 0;
        }
        return cur_len + len;
      }
      return cur_len;
    default:
      return 0;
  }
  if (len < 0) {
    return 0;
  }

  cur_len += len;
  if (entry.start_ns == 0 && !output_present_bytes) {
    return cur_len;
  }

  len = snprintf(&buffer[cur_len], buffer_len - cur_len, " %" PRIu64 " %" PRIu64, entry.start_ns,
                 entry.end_ns);
  if (len < 0) {
    return 0;
  }

  cur_len += len;
  if (!output_present_bytes) {
    return cur_len;
  }

  len = snprintf(&buffer[cur_len], buffer_len - cur_len, " %" PRId64, entry.present_bytes);
  if (len < 0) {
    return 0;
  }
  return cur_len + len;
}

std::string CreateStringFromEntry(const Entry& entry) {
  std::string line(kBufferLen, '\0');

  size_t size = FormatEntry(entry, line.data(), line.size());
  if (size == 0) {
    return "";
  }
  line.resize(size);
  return line;
}

bool WriteEntryToFd(int fd, const Entry& entry) {
  char buffer[kBufferLen];
  size_t size = FormatEntry(entry, buffer, sizeof(buffer));
  if (size == 0 || size == sizeof(buffer)) {
    return false;
  }
  buffer[size++] = '\n';
  buffer[size] = '\0';
  ssize_t bytes = TEMP_FAILURE_RETRY(write(fd, buffer, size));
  if (bytes < 0 || static_cast<size_t>(bytes) != size) {
    return false;
  }
  return true;
}

}  // namespace memory_trace

Messung V0.5 in Prozent
C=88 H=93 G=90

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-06-28) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik